// SPDX-License-Identifier: GPL-2.0 /* * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c * * Copyright (C) 2005, Intec Automation Inc. * Copyright (C) 2014, Freescale Semiconductor, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "core.h" /* Define max times to check status register before we give up. */ /* * For everything but full-chip erase; probably could be much smaller, but kept * around for safety for now */ #define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) /* * For full-chip erase, calibrated to a 2MB flash (M25P16); should be scaled up * for larger flash */ #define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ) #define SPI_NOR_MAX_ADDR_WIDTH 4 #define JEDEC_MFR(info) ((info)->id[0]) /** * spi_nor_spimem_bounce() - check if a bounce buffer is needed for the data * transfer * @nor: pointer to 'struct spi_nor' * @op: pointer to 'struct spi_mem_op' template for transfer * * If we have to use the bounce buffer, the data field in @op will be updated. * * Return: true if the bounce buffer is needed, false if not */ static bool spi_nor_spimem_bounce(struct spi_nor *nor, struct spi_mem_op *op) { /* op->data.buf.in occupies the same memory as op->data.buf.out */ if (object_is_on_stack(op->data.buf.in) || !virt_addr_valid(op->data.buf.in)) { if (op->data.nbytes > nor->bouncebuf_size) op->data.nbytes = nor->bouncebuf_size; op->data.buf.in = nor->bouncebuf; return true; } return false; } /** * spi_nor_spimem_exec_op() - execute a memory operation * @nor: pointer to 'struct spi_nor' * @op: pointer to 'struct spi_mem_op' template for transfer * * Return: 0 on success, -error otherwise. */ static int spi_nor_spimem_exec_op(struct spi_nor *nor, struct spi_mem_op *op) { int error; error = spi_mem_adjust_op_size(nor->spimem, op); if (error) return error; return spi_mem_exec_op(nor->spimem, op); } /** * spi_nor_spimem_read_data() - read data from flash's memory region via * spi-mem * @nor: pointer to 'struct spi_nor' * @from: offset to read from * @len: number of bytes to read * @buf: pointer to dst buffer * * Return: number of bytes read successfully, -errno otherwise */ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from, size_t len, u8 *buf) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1), SPI_MEM_OP_ADDR(nor->addr_width, from, 1), SPI_MEM_OP_DUMMY(nor->read_dummy, 1), SPI_MEM_OP_DATA_IN(len, buf, 1)); bool usebouncebuf; ssize_t nbytes; int error; /* get transfer protocols. */ op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); op.dummy.buswidth = op.addr.buswidth; op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); /* convert the dummy cycles to the number of bytes */ op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; usebouncebuf = spi_nor_spimem_bounce(nor, &op); if (nor->dirmap.rdesc) { nbytes = spi_mem_dirmap_read(nor->dirmap.rdesc, op.addr.val, op.data.nbytes, op.data.buf.in); } else { error = spi_nor_spimem_exec_op(nor, &op); if (error) return error; nbytes = op.data.nbytes; } if (usebouncebuf && nbytes > 0) memcpy(buf, op.data.buf.in, nbytes); return nbytes; } /** * spi_nor_read_data() - read data from flash memory * @nor: pointer to 'struct spi_nor' * @from: offset to read from * @len: number of bytes to read * @buf: pointer to dst buffer * * Return: number of bytes read successfully, -errno otherwise */ ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, u8 *buf) { if (nor->spimem) return spi_nor_spimem_read_data(nor, from, len, buf); return nor->controller_ops->read(nor, from, len, buf); } /** * spi_nor_spimem_write_data() - write data to flash memory via * spi-mem * @nor: pointer to 'struct spi_nor' * @to: offset to write to * @len: number of bytes to write * @buf: pointer to src buffer * * Return: number of bytes written successfully, -errno otherwise */ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t to, size_t len, const u8 *buf) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1), SPI_MEM_OP_ADDR(nor->addr_width, to, 1), SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(len, buf, 1)); ssize_t nbytes; int error; op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); op.data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) op.addr.nbytes = 0; if (spi_nor_spimem_bounce(nor, &op)) memcpy(nor->bouncebuf, buf, op.data.nbytes); if (nor->dirmap.wdesc) { nbytes = spi_mem_dirmap_write(nor->dirmap.wdesc, op.addr.val, op.data.nbytes, op.data.buf.out); } else { error = spi_nor_spimem_exec_op(nor, &op); if (error) return error; nbytes = op.data.nbytes; } return nbytes; } /** * spi_nor_write_data() - write data to flash memory * @nor: pointer to 'struct spi_nor' * @to: offset to write to * @len: number of bytes to write * @buf: pointer to src buffer * * Return: number of bytes written successfully, -errno otherwise */ ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len, const u8 *buf) { if (nor->spimem) return spi_nor_spimem_write_data(nor, to, len, buf); return nor->controller_ops->write(nor, to, len, buf); } /** * spi_nor_write_enable() - Set write enable latch with Write Enable command. * @nor: pointer to 'struct spi_nor'. * * Return: 0 on success, -errno otherwise. */ int spi_nor_write_enable(struct spi_nor *nor) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WREN, NULL, 0); } if (ret) dev_dbg(nor->dev, "error %d on Write Enable\n", ret); return ret; } /** * spi_nor_write_disable() - Send Write Disable instruction to the chip. * @nor: pointer to 'struct spi_nor'. * * Return: 0 on success, -errno otherwise. */ int spi_nor_write_disable(struct spi_nor *nor) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); } if (ret) dev_dbg(nor->dev, "error %d on Write Disable\n", ret); return ret; } /** * spi_nor_read_sr() - Read the Status Register. * @nor: pointer to 'struct spi_nor'. * @sr: pointer to a DMA-able buffer where the value of the * Status Register will be written. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_read_sr(struct spi_nor *nor, u8 *sr) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, sr, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDSR, sr, 1); } if (ret) dev_dbg(nor->dev, "error %d reading SR\n", ret); return ret; } /** * spi_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. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_read_fsr(struct spi_nor *nor, u8 *fsr) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, fsr, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = 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; } /** * spi_nor_read_cr() - Read the Configuration Register using the * SPINOR_OP_RDCR (35h) command. * @nor: pointer to 'struct spi_nor' * @cr: pointer to a DMA-able buffer where the value of the * Configuration Register will be written. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_read_cr(struct spi_nor *nor, u8 *cr) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, cr, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDCR, cr, 1); } if (ret) dev_dbg(nor->dev, "error %d reading CR\n", ret); return ret; } /** * spi_nor_set_4byte_addr_mode() - Enter/Exit 4-byte address mode. * @nor: pointer to 'struct spi_nor'. * @enable: true to enter the 4-byte address mode, false to exit the 4-byte * address mode. * * Return: 0 on success, -errno otherwise. */ int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, NULL, 0); } if (ret) dev_dbg(nor->dev, "error %d setting 4-byte mode\n", ret); return ret; } /** * st_micron_set_4byte_addr_mode() - Set 4-byte address mode for ST and Micron * flashes. * @nor: pointer to 'struct spi_nor'. * @enable: true to enter the 4-byte address mode, false to exit the 4-byte * address mode. * * Return: 0 on success, -errno otherwise. */ static int st_micron_set_4byte_addr_mode(struct spi_nor *nor, bool enable) { int ret; ret = spi_nor_write_enable(nor); if (ret) return ret; ret = spi_nor_set_4byte_addr_mode(nor, enable); if (ret) return ret; return spi_nor_write_disable(nor); } /** * spansion_set_4byte_addr_mode() - Set 4-byte address mode for Spansion * flashes. * @nor: pointer to 'struct spi_nor'. * @enable: true to enter the 4-byte address mode, false to exit the 4-byte * address mode. * * Return: 0 on success, -errno otherwise. */ static int spansion_set_4byte_addr_mode(struct spi_nor *nor, bool enable) { int ret; nor->bouncebuf[0] = enable << 7; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, SPINOR_OP_BRWR, nor->bouncebuf, 1); } if (ret) dev_dbg(nor->dev, "error %d setting 4-byte mode\n", ret); return ret; } /** * spi_nor_write_ear() - Write Extended Address Register. * @nor: pointer to 'struct spi_nor'. * @ear: value to write to the Extended Address Register. * * Return: 0 on success, -errno otherwise. */ int spi_nor_write_ear(struct spi_nor *nor, u8 ear) { int ret; nor->bouncebuf[0] = ear; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WREAR, nor->bouncebuf, 1); } if (ret) dev_dbg(nor->dev, "error %d writing EAR\n", ret); return ret; } /** * winbond_set_4byte_addr_mode() - Set 4-byte address mode for Winbond flashes. * @nor: pointer to 'struct spi_nor'. * @enable: true to enter the 4-byte address mode, false to exit the 4-byte * address mode. * * Return: 0 on success, -errno otherwise. */ static int winbond_set_4byte_addr_mode(struct spi_nor *nor, bool enable) { int ret; ret = spi_nor_set_4byte_addr_mode(nor, enable); if (ret || enable) return ret; /* * On Winbond W25Q256FV, leaving 4byte mode causes the Extended Address * Register to be set to 1, so all 3-byte-address reads come from the * second 16M. We must clear the register to enable normal behavior. */ ret = spi_nor_write_enable(nor); if (ret) return ret; ret = spi_nor_write_ear(nor, 0); if (ret) return ret; return spi_nor_write_disable(nor); } /** * spi_nor_xread_sr() - Read the Status Register on S3AN flashes. * @nor: pointer to 'struct spi_nor'. * @sr: pointer to a DMA-able buffer where the value of the * Status Register will be written. * * Return: 0 on success, -errno otherwise. */ int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_XRDSR, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, sr, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->read_reg(nor, SPINOR_OP_XRDSR, sr, 1); } if (ret) dev_dbg(nor->dev, "error %d reading XRDSR\n", ret); return ret; } /** * spi_nor_xsr_ready() - Query the Status Register of the S3AN flash to see if * the flash is ready for new commands. * @nor: pointer to 'struct spi_nor'. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_xsr_ready(struct spi_nor *nor) { int ret; ret = spi_nor_xread_sr(nor, nor->bouncebuf); if (ret) return ret; return !!(nor->bouncebuf[0] & XSR_RDY); } /** * spi_nor_clear_sr() - Clear the Status Register. * @nor: pointer to 'struct spi_nor'. */ static void spi_nor_clear_sr(struct spi_nor *nor) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, SPINOR_OP_CLSR, NULL, 0); } if (ret) dev_dbg(nor->dev, "error %d clearing SR\n", ret); } /** * spi_nor_sr_ready() - Query the Status Register to see if the flash is ready * for new commands. * @nor: pointer to 'struct spi_nor'. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_sr_ready(struct spi_nor *nor) { int ret = spi_nor_read_sr(nor, nor->bouncebuf); if (ret) return ret; if (nor->flags & SNOR_F_USE_CLSR && 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"); spi_nor_clear_sr(nor); return -EIO; } return !(nor->bouncebuf[0] & SR_WIP); } /** * spi_nor_clear_fsr() - Clear the Flag Status Register. * @nor: pointer to 'struct spi_nor'. */ static void spi_nor_clear_fsr(struct spi_nor *nor) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, SPINOR_OP_CLFSR, NULL, 0); } if (ret) dev_dbg(nor->dev, "error %d clearing FSR\n", ret); } /** * spi_nor_fsr_ready() - Query the Flag Status Register to see if the flash is * ready for new commands. * @nor: pointer to 'struct spi_nor'. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_fsr_ready(struct spi_nor *nor) { int ret = spi_nor_read_fsr(nor, nor->bouncebuf); if (ret) return 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"); spi_nor_clear_fsr(nor); return -EIO; } return nor->bouncebuf[0] & FSR_READY; } /** * spi_nor_ready() - Query the flash to see if it is ready for new commands. * @nor: pointer to 'struct spi_nor'. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_ready(struct spi_nor *nor) { int sr, fsr; if (nor->flags & SNOR_F_READY_XSR_RDY) sr = spi_nor_xsr_ready(nor); else sr = spi_nor_sr_ready(nor); if (sr < 0) return sr; fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; if (fsr < 0) return fsr; return sr && fsr; } /** * spi_nor_wait_till_ready_with_timeout() - Service routine to read the * Status Register until ready, or timeout occurs. * @nor: pointer to "struct spi_nor". * @timeout_jiffies: jiffies to wait until timeout. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor, unsigned long timeout_jiffies) { unsigned long deadline; int timeout = 0, ret; deadline = jiffies + timeout_jiffies; while (!timeout) { if (time_after_eq(jiffies, deadline)) timeout = 1; ret = spi_nor_ready(nor); if (ret < 0) return ret; if (ret) return 0; cond_resched(); } dev_dbg(nor->dev, "flash operation timed out\n"); return -ETIMEDOUT; } /** * spi_nor_wait_till_ready() - Wait for a predefined amount of time for the * flash to be ready, or timeout occurs. * @nor: pointer to "struct spi_nor". * * Return: 0 on success, -errno otherwise. */ int spi_nor_wait_till_ready(struct spi_nor *nor) { return spi_nor_wait_till_ready_with_timeout(nor, DEFAULT_READY_WAIT_JIFFIES); } /** * spi_nor_write_sr() - Write the Status Register. * @nor: pointer to 'struct spi_nor'. * @sr: pointer to DMA-able buffer to write to the Status Register. * @len: number of bytes to write to the Status Register. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_write_sr(struct spi_nor *nor, const u8 *sr, size_t len) { int ret; ret = spi_nor_write_enable(nor); if (ret) return ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(len, sr, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WRSR, sr, len); } if (ret) { dev_dbg(nor->dev, "error %d writing SR\n", ret); return ret; } return spi_nor_wait_till_ready(nor); } /** * spi_nor_write_sr1_and_check() - Write one byte to the Status Register 1 and * ensure that the byte written match the received value. * @nor: pointer to a 'struct spi_nor'. * @sr1: byte value to be written to the Status Register. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_write_sr1_and_check(struct spi_nor *nor, u8 sr1) { int ret; nor->bouncebuf[0] = sr1; ret = spi_nor_write_sr(nor, nor->bouncebuf, 1); if (ret) return ret; ret = spi_nor_read_sr(nor, nor->bouncebuf); if (ret) return ret; if (nor->bouncebuf[0] != sr1) { dev_dbg(nor->dev, "SR1: read back test failed\n"); return -EIO; } return 0; } /** * spi_nor_write_16bit_sr_and_check() - Write the Status Register 1 and the * Status Register 2 in one shot. Ensure that the byte written in the Status * Register 1 match the received value, and that the 16-bit Write did not * affect what was already in the Status Register 2. * @nor: pointer to a 'struct spi_nor'. * @sr1: byte value to be written to the Status Register 1. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1) { int ret; u8 *sr_cr = nor->bouncebuf; u8 cr_written; /* Make sure we don't overwrite the contents of Status Register 2. */ if (!(nor->flags & SNOR_F_NO_READ_CR)) { ret = spi_nor_read_cr(nor, &sr_cr[1]); if (ret) return ret; } else if (nor->params.quad_enable) { /* * If the Status Register 2 Read command (35h) is not * supported, we should at least be sure we don't * change the value of the SR2 Quad Enable bit. * * We can safely assume that when the Quad Enable method is * set, the value of the QE bit is one, as a consequence of the * nor->params.quad_enable() call. * * We can safely assume that the Quad Enable bit is present in * the Status Register 2 at BIT(1). According to the JESD216 * revB standard, BFPT DWORDS[15], bits 22:20, the 16-bit * Write Status (01h) command is available just for the cases * in which the QE bit is described in SR2 at BIT(1). */ sr_cr[1] = SR2_QUAD_EN_BIT1; } else { sr_cr[1] = 0; } sr_cr[0] = sr1; ret = spi_nor_write_sr(nor, sr_cr, 2); if (ret) return ret; if (nor->flags & SNOR_F_NO_READ_CR) return 0; cr_written = sr_cr[1]; ret = spi_nor_read_cr(nor, &sr_cr[1]); if (ret) return ret; if (cr_written != sr_cr[1]) { dev_dbg(nor->dev, "CR: read back test failed\n"); return -EIO; } return 0; } /** * spi_nor_write_16bit_cr_and_check() - Write the Status Register 1 and the * Configuration Register in one shot. Ensure that the byte written in the * Configuration Register match the received value, and that the 16-bit Write * did not affect what was already in the Status Register 1. * @nor: pointer to a 'struct spi_nor'. * @cr: byte value to be written to the Configuration Register. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_write_16bit_cr_and_check(struct spi_nor *nor, u8 cr) { int ret; u8 *sr_cr = nor->bouncebuf; u8 sr_written; /* Keep the current value of the Status Register 1. */ ret = spi_nor_read_sr(nor, sr_cr); if (ret) return ret; sr_cr[1] = cr; ret = spi_nor_write_sr(nor, sr_cr, 2); if (ret) return ret; sr_written = sr_cr[0]; ret = spi_nor_read_sr(nor, sr_cr); if (ret) return ret; if (sr_written != sr_cr[0]) { dev_dbg(nor->dev, "SR: Read back test failed\n"); return -EIO; } if (nor->flags & SNOR_F_NO_READ_CR) return 0; ret = spi_nor_read_cr(nor, &sr_cr[1]); if (ret) return ret; if (cr != sr_cr[1]) { dev_dbg(nor->dev, "CR: read back test failed\n"); return -EIO; } return 0; } /** * spi_nor_write_sr_and_check() - Write the Status Register 1 and ensure that * the byte written match the received value without affecting other bits in the * Status Register 1 and 2. * @nor: pointer to a 'struct spi_nor'. * @sr1: byte value to be written to the Status Register. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1) { if (nor->flags & SNOR_F_HAS_16BIT_SR) return spi_nor_write_16bit_sr_and_check(nor, sr1); return spi_nor_write_sr1_and_check(nor, sr1); } /** * spi_nor_write_sr2() - Write the Status Register 2 using the * SPINOR_OP_WRSR2 (3eh) command. * @nor: pointer to 'struct spi_nor'. * @sr2: pointer to DMA-able buffer to write to the Status Register 2. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_write_sr2(struct spi_nor *nor, const u8 *sr2) { int ret; ret = spi_nor_write_enable(nor); if (ret) return ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(1, sr2, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, SPINOR_OP_WRSR2, sr2, 1); } if (ret) { dev_dbg(nor->dev, "error %d writing SR2\n", ret); return ret; } return spi_nor_wait_till_ready(nor); } /** * spi_nor_read_sr2() - Read the Status Register 2 using the * SPINOR_OP_RDSR2 (3fh) command. * @nor: pointer to 'struct spi_nor'. * @sr2: pointer to DMA-able buffer where the value of the * Status Register 2 will be written. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_read_sr2(struct spi_nor *nor, u8 *sr2) { int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(1, sr2, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDSR2, sr2, 1); } if (ret) dev_dbg(nor->dev, "error %d reading SR2\n", ret); return ret; } /** * spi_nor_erase_chip() - Erase the entire flash memory. * @nor: pointer to 'struct spi_nor'. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_erase_chip(struct spi_nor *nor) { int ret; dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10)); if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0); } if (ret) dev_dbg(nor->dev, "error %d erasing chip\n", ret); return ret; } static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size) { size_t i; for (i = 0; i < size; i++) if (table[i][0] == opcode) return table[i][1]; /* No conversion found, keep input op code. */ return opcode; } u8 spi_nor_convert_3to4_read(u8 opcode) { static const u8 spi_nor_3to4_read[][2] = { { SPINOR_OP_READ, SPINOR_OP_READ_4B }, { SPINOR_OP_READ_FAST, SPINOR_OP_READ_FAST_4B }, { SPINOR_OP_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B }, { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B }, { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B }, { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B }, { SPINOR_OP_READ_1_1_8, SPINOR_OP_READ_1_1_8_4B }, { SPINOR_OP_READ_1_8_8, SPINOR_OP_READ_1_8_8_4B }, { SPINOR_OP_READ_1_1_1_DTR, SPINOR_OP_READ_1_1_1_DTR_4B }, { SPINOR_OP_READ_1_2_2_DTR, SPINOR_OP_READ_1_2_2_DTR_4B }, { SPINOR_OP_READ_1_4_4_DTR, SPINOR_OP_READ_1_4_4_DTR_4B }, }; return spi_nor_convert_opcode(opcode, spi_nor_3to4_read, ARRAY_SIZE(spi_nor_3to4_read)); } static u8 spi_nor_convert_3to4_program(u8 opcode) { static const u8 spi_nor_3to4_program[][2] = { { SPINOR_OP_PP, SPINOR_OP_PP_4B }, { SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B }, { SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B }, { SPINOR_OP_PP_1_1_8, SPINOR_OP_PP_1_1_8_4B }, { SPINOR_OP_PP_1_8_8, SPINOR_OP_PP_1_8_8_4B }, }; return spi_nor_convert_opcode(opcode, spi_nor_3to4_program, ARRAY_SIZE(spi_nor_3to4_program)); } static u8 spi_nor_convert_3to4_erase(u8 opcode) { static const u8 spi_nor_3to4_erase[][2] = { { SPINOR_OP_BE_4K, SPINOR_OP_BE_4K_4B }, { SPINOR_OP_BE_32K, SPINOR_OP_BE_32K_4B }, { SPINOR_OP_SE, SPINOR_OP_SE_4B }, }; return spi_nor_convert_opcode(opcode, spi_nor_3to4_erase, ARRAY_SIZE(spi_nor_3to4_erase)); } static void spi_nor_set_4byte_opcodes(struct spi_nor *nor) { nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode); nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode); if (!spi_nor_has_uniform_erase(nor)) { struct spi_nor_erase_map *map = &nor->params.erase_map; struct spi_nor_erase_type *erase; int i; for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) { erase = &map->erase_type[i]; erase->opcode = spi_nor_convert_3to4_erase(erase->opcode); } } } int spi_nor_lock_and_prep(struct spi_nor *nor) { int ret = 0; mutex_lock(&nor->lock); if (nor->controller_ops && nor->controller_ops->prepare) { ret = nor->controller_ops->prepare(nor); if (ret) { mutex_unlock(&nor->lock); return ret; } } return ret; } void spi_nor_unlock_and_unprep(struct spi_nor *nor) { if (nor->controller_ops && nor->controller_ops->unprepare) nor->controller_ops->unprepare(nor); mutex_unlock(&nor->lock); } /* * This code converts an address to the Default Address Mode, that has non * power of two page sizes. We must support this mode because it is the default * mode supported by Xilinx tools, it can access the whole flash area and * changing over to the Power-of-two mode is irreversible and corrupts the * original data. * Addr can safely be unsigned int, the biggest S3AN device is smaller than * 4 MiB. */ static u32 s3an_convert_addr(struct spi_nor *nor, u32 addr) { u32 offset, page; offset = addr % nor->page_size; page = addr / nor->page_size; page <<= (nor->page_size > 512) ? 10 : 9; return page | offset; } static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr) { if (!nor->params.convert_addr) return addr; return nor->params.convert_addr(nor, addr); } /* * Initiate the erasure of a single sector */ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) { int i; addr = spi_nor_convert_addr(nor, addr); if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->erase_opcode, 1), SPI_MEM_OP_ADDR(nor->addr_width, addr, 1), SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DATA); return spi_mem_exec_op(nor->spimem, &op); } else if (nor->controller_ops->erase) { return nor->controller_ops->erase(nor, addr); } /* * Default implementation, if driver doesn't have a specialized HW * control */ for (i = nor->addr_width - 1; i >= 0; i--) { nor->bouncebuf[i] = addr & 0xff; addr >>= 8; } return nor->controller_ops->write_reg(nor, nor->erase_opcode, nor->bouncebuf, nor->addr_width); } /** * spi_nor_div_by_erase_size() - calculate remainder and update new dividend * @erase: pointer to a structure that describes a SPI NOR erase type * @dividend: dividend value * @remainder: pointer to u32 remainder (will be updated) * * Return: the result of the division */ static u64 spi_nor_div_by_erase_size(const struct spi_nor_erase_type *erase, u64 dividend, u32 *remainder) { /* JEDEC JESD216B Standard imposes erase sizes to be power of 2. */ *remainder = (u32)dividend & erase->size_mask; return dividend >> erase->size_shift; } /** * spi_nor_find_best_erase_type() - find the best erase type for the given * offset in the serial flash memory and the * number of bytes to erase. The region in * which the address fits is expected to be * provided. * @map: the erase map of the SPI NOR * @region: pointer to a structure that describes a SPI NOR erase region * @addr: offset in the serial flash memory * @len: number of bytes to erase * * Return: a pointer to the best fitted erase type, NULL otherwise. */ static const struct spi_nor_erase_type * spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map, const struct spi_nor_erase_region *region, u64 addr, u32 len) { const struct spi_nor_erase_type *erase; u32 rem; int i; u8 erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; /* * Erase types are ordered by size, with the smallest erase type at * index 0. */ for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { /* Does the erase region support the tested erase type? */ if (!(erase_mask & BIT(i))) continue; erase = &map->erase_type[i]; /* Don't erase more than what the user has asked for. */ if (erase->size > len) continue; /* Alignment is not mandatory for overlaid regions */ if (region->offset & SNOR_OVERLAID_REGION) return erase; spi_nor_div_by_erase_size(erase, addr, &rem); if (rem) continue; else return erase; } return NULL; } /** * spi_nor_region_next() - get the next spi nor region * @region: pointer to a structure that describes a SPI NOR erase region * * Return: the next spi nor region or NULL if last region. */ struct spi_nor_erase_region * spi_nor_region_next(struct spi_nor_erase_region *region) { if (spi_nor_region_is_last(region)) return NULL; region++; return region; } /** * spi_nor_find_erase_region() - find the region of the serial flash memory in * which the offset fits * @map: the erase map of the SPI NOR * @addr: offset in the serial flash memory * * Return: a pointer to the spi_nor_erase_region struct, ERR_PTR(-errno) * otherwise. */ static struct spi_nor_erase_region * spi_nor_find_erase_region(const struct spi_nor_erase_map *map, u64 addr) { struct spi_nor_erase_region *region = map->regions; u64 region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; u64 region_end = region_start + region->size; while (addr < region_start || addr >= region_end) { region = spi_nor_region_next(region); if (!region) return ERR_PTR(-EINVAL); region_start = region->offset & ~SNOR_ERASE_FLAGS_MASK; region_end = region_start + region->size; } return region; } /** * spi_nor_init_erase_cmd() - initialize an erase command * @region: pointer to a structure that describes a SPI NOR erase region * @erase: pointer to a structure that describes a SPI NOR erase type * * Return: the pointer to the allocated erase command, ERR_PTR(-errno) * otherwise. */ static struct spi_nor_erase_command * spi_nor_init_erase_cmd(const struct spi_nor_erase_region *region, const struct spi_nor_erase_type *erase) { struct spi_nor_erase_command *cmd; cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) return ERR_PTR(-ENOMEM); INIT_LIST_HEAD(&cmd->list); cmd->opcode = erase->opcode; cmd->count = 1; if (region->offset & SNOR_OVERLAID_REGION) cmd->size = region->size; else cmd->size = erase->size; return cmd; } /** * spi_nor_destroy_erase_cmd_list() - destroy erase command list * @erase_list: list of erase commands */ static void spi_nor_destroy_erase_cmd_list(struct list_head *erase_list) { struct spi_nor_erase_command *cmd, *next; list_for_each_entry_safe(cmd, next, erase_list, list) { list_del(&cmd->list); kfree(cmd); } } /** * spi_nor_init_erase_cmd_list() - initialize erase command list * @nor: pointer to a 'struct spi_nor' * @erase_list: list of erase commands to be executed once we validate that the * erase can be performed * @addr: offset in the serial flash memory * @len: number of bytes to erase * * Builds the list of best fitted erase commands and verifies if the erase can * be performed. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor, struct list_head *erase_list, u64 addr, u32 len) { const struct spi_nor_erase_map *map = &nor->params.erase_map; const struct spi_nor_erase_type *erase, *prev_erase = NULL; struct spi_nor_erase_region *region; struct spi_nor_erase_command *cmd = NULL; u64 region_end; int ret = -EINVAL; region = spi_nor_find_erase_region(map, addr); if (IS_ERR(region)) return PTR_ERR(region); region_end = spi_nor_region_end(region); while (len) { erase = spi_nor_find_best_erase_type(map, region, addr, len); if (!erase) goto destroy_erase_cmd_list; if (prev_erase != erase || region->offset & SNOR_OVERLAID_REGION) { cmd = spi_nor_init_erase_cmd(region, erase); if (IS_ERR(cmd)) { ret = PTR_ERR(cmd); goto destroy_erase_cmd_list; } list_add_tail(&cmd->list, erase_list); } else { cmd->count++; } addr += cmd->size; len -= cmd->size; if (len && addr >= region_end) { region = spi_nor_region_next(region); if (!region) goto destroy_erase_cmd_list; region_end = spi_nor_region_end(region); } prev_erase = erase; } return 0; destroy_erase_cmd_list: spi_nor_destroy_erase_cmd_list(erase_list); return ret; } /** * spi_nor_erase_multi_sectors() - perform a non-uniform erase * @nor: pointer to a 'struct spi_nor' * @addr: offset in the serial flash memory * @len: number of bytes to erase * * Build a list of best fitted erase commands and execute it once we validate * that the erase can be performed. * * Return: 0 on success, -errno otherwise. */ static int spi_nor_erase_multi_sectors(struct spi_nor *nor, u64 addr, u32 len) { LIST_HEAD(erase_list); struct spi_nor_erase_command *cmd, *next; int ret; ret = spi_nor_init_erase_cmd_list(nor, &erase_list, addr, len); if (ret) return ret; list_for_each_entry_safe(cmd, next, &erase_list, list) { nor->erase_opcode = cmd->opcode; while (cmd->count) { ret = spi_nor_write_enable(nor); if (ret) goto destroy_erase_cmd_list; ret = spi_nor_erase_sector(nor, addr); if (ret) goto destroy_erase_cmd_list; addr += cmd->size; cmd->count--; ret = spi_nor_wait_till_ready(nor); if (ret) goto destroy_erase_cmd_list; } list_del(&cmd->list); kfree(cmd); } return 0; destroy_erase_cmd_list: spi_nor_destroy_erase_cmd_list(&erase_list); return ret; } /* * Erase an address range on the nor chip. The address range may extend * one or more erase sectors. Return an error is there is a problem erasing. */ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) { struct spi_nor *nor = mtd_to_spi_nor(mtd); u32 addr, len; uint32_t rem; int ret; dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, (long long)instr->len); if (spi_nor_has_uniform_erase(nor)) { div_u64_rem(instr->len, mtd->erasesize, &rem); if (rem) return -EINVAL; } addr = instr->addr; len = instr->len; ret = spi_nor_lock_and_prep(nor); if (ret) return ret; /* whole-chip erase? */ if (len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) { unsigned long timeout; ret = spi_nor_write_enable(nor); if (ret) goto erase_err; ret = spi_nor_erase_chip(nor); if (ret) goto erase_err; /* * Scale the timeout linearly with the size of the flash, with * a minimum calibrated to an old 2MB flash. We could try to * pull these from CFI/SFDP, but these values should be good * enough for now. */ timeout = max(CHIP_ERASE_2MB_READY_WAIT_JIFFIES, CHIP_ERASE_2MB_READY_WAIT_JIFFIES * (unsigned long)(mtd->size / SZ_2M)); ret = spi_nor_wait_till_ready_with_timeout(nor, timeout); if (ret) goto erase_err; /* REVISIT in some cases we could speed up erasing large regions * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up * to use "small sector erase", but that's not always optimal. */ /* "sector"-at-a-time erase */ } else if (spi_nor_has_uniform_erase(nor)) { while (len) { ret = spi_nor_write_enable(nor); if (ret) goto erase_err; ret = spi_nor_erase_sector(nor, addr); if (ret) goto erase_err; addr += mtd->erasesize; len -= mtd->erasesize; ret = spi_nor_wait_till_ready(nor); if (ret) goto erase_err; } /* erase multiple sectors */ } else { ret = spi_nor_erase_multi_sectors(nor, addr, len); if (ret) goto erase_err; } ret = spi_nor_write_disable(nor); erase_err: spi_nor_unlock_and_unprep(nor); return ret; } static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs, uint64_t *len) { struct mtd_info *mtd = &nor->mtd; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 tb_mask = SR_TB_BIT5; int pow; if (nor->flags & SNOR_F_HAS_SR_TB_BIT6) tb_mask = SR_TB_BIT6; if (!(sr & mask)) { /* No protection */ *ofs = 0; *len = 0; } else { pow = ((sr & mask) ^ mask) >> SR_BP_SHIFT; *len = mtd->size >> pow; if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask) *ofs = 0; else *ofs = mtd->size - *len; } } /* * Return 1 if the entire region is locked (if @locked is true) or unlocked (if * @locked is false); 0 otherwise */ static int spi_nor_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, u8 sr, bool locked) { loff_t lock_offs; uint64_t lock_len; if (!len) return 1; spi_nor_get_locked_range_sr(nor, sr, &lock_offs, &lock_len); if (locked) /* Requested range is a sub-range of locked range */ return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); else /* Requested range does not overlap with locked range */ return (ofs >= lock_offs + lock_len) || (ofs + len <= lock_offs); } static int spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, u8 sr) { return spi_nor_check_lock_status_sr(nor, ofs, len, sr, true); } static int spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, u8 sr) { return spi_nor_check_lock_status_sr(nor, ofs, len, sr, false); } /* * Lock a region of the flash. Compatible with ST Micro and similar flash. * Supports the block protection bits BP{0,1,2} in the status register * (SR). Does not support these features found in newer SR bitfields: * - SEC: sector/block protect - only handle SEC=0 (block protect) * - CMP: complement protect - only support CMP=0 (range is not complemented) * * Support for the following is provided conditionally for some flash: * - TB: top/bottom protect * * Sample table portion for 8MB flash (Winbond w25q64fw): * * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion * -------------------------------------------------------------------------- * X | X | 0 | 0 | 0 | NONE | NONE * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 * X | X | 1 | 1 | 1 | 8 MB | ALL * ------|-------|-------|-------|-------|---------------|------------------- * 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64 * 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32 * 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16 * 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8 * 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4 * 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2 * * Returns negative on errors, 0 on success. */ static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) { struct mtd_info *mtd = &nor->mtd; int ret, status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 tb_mask = SR_TB_BIT5; u8 pow, val; loff_t lock_len; bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; ret = spi_nor_read_sr(nor, nor->bouncebuf); if (ret) return ret; status_old = nor->bouncebuf[0]; /* If nothing in our range is unlocked, we don't need to do anything */ if (spi_nor_is_locked_sr(nor, ofs, len, status_old)) return 0; /* If anything below us is unlocked, we can't use 'bottom' protection */ if (!spi_nor_is_locked_sr(nor, 0, ofs, status_old)) can_be_bottom = false; /* If anything above us is unlocked, we can't use 'top' protection */ if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), status_old)) can_be_top = false; if (!can_be_bottom && !can_be_top) return -EINVAL; /* Prefer top, if both are valid */ use_top = can_be_top; /* lock_len: length of region that should end up locked */ if (use_top) lock_len = mtd->size - ofs; else lock_len = ofs + len; if (nor->flags & SNOR_F_HAS_SR_TB_BIT6) tb_mask = SR_TB_BIT6; /* * Need smallest pow such that: * * 1 / (2^pow) <= (len / size) * * so (assuming power-of-2 size) we do: * * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) */ pow = ilog2(mtd->size) - ilog2(lock_len); val = mask - (pow << SR_BP_SHIFT); if (val & ~mask) return -EINVAL; /* Don't "lock" with no region! */ if (!(val & mask)) return -EINVAL; status_new = (status_old & ~mask & ~tb_mask) | val; /* Disallow further writes if WP pin is asserted */ status_new |= SR_SRWD; if (!use_top) status_new |= tb_mask; /* Don't bother if they're the same */ if (status_new == status_old) return 0; /* Only modify protection if it will not unlock other areas */ if ((status_new & mask) < (status_old & mask)) return -EINVAL; return spi_nor_write_sr_and_check(nor, status_new); } /* * Unlock a region of the flash. See spi_nor_sr_lock() for more info * * Returns negative on errors, 0 on success. */ static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) { struct mtd_info *mtd = &nor->mtd; int ret, status_old, status_new; u8 mask = SR_BP2 | SR_BP1 | SR_BP0; u8 tb_mask = SR_TB_BIT5; u8 pow, val; loff_t lock_len; bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB; bool use_top; ret = spi_nor_read_sr(nor, nor->bouncebuf); if (ret) return ret; status_old = nor->bouncebuf[0]; /* If nothing in our range is locked, we don't need to do anything */ if (spi_nor_is_unlocked_sr(nor, ofs, len, status_old)) return 0; /* If anything below us is locked, we can't use 'top' protection */ if (!spi_nor_is_unlocked_sr(nor, 0, ofs, status_old)) can_be_top = false; /* If anything above us is locked, we can't use 'bottom' protection */ if (!spi_nor_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len), status_old)) can_be_bottom = false; if (!can_be_bottom && !can_be_top) return -EINVAL; /* Prefer top, if both are valid */ use_top = can_be_top; /* lock_len: length of region that should remain locked */ if (use_top) lock_len = mtd->size - (ofs + len); else lock_len = ofs; if (nor->flags & SNOR_F_HAS_SR_TB_BIT6) tb_mask = SR_TB_BIT6; /* * Need largest pow such that: * * 1 / (2^pow) >= (len / size) * * so (assuming power-of-2 size) we do: * * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) */ pow = ilog2(mtd->size) - order_base_2(lock_len); if (lock_len == 0) { val = 0; /* fully unlocked */ } else { val = mask - (pow << SR_BP_SHIFT); /* Some power-of-two sizes are not supported */ if (val & ~mask) return -EINVAL; } status_new = (status_old & ~mask & ~tb_mask) | val; /* Don't protect status register if we're fully unlocked */ if (lock_len == 0) status_new &= ~SR_SRWD; if (!use_top) status_new |= tb_mask; /* Don't bother if they're the same */ if (status_new == status_old) return 0; /* Only modify protection if it will not lock other areas */ if ((status_new & mask) > (status_old & mask)) return -EINVAL; return spi_nor_write_sr_and_check(nor, status_new); } /* * Check if a region of the flash is (completely) locked. See spi_nor_sr_lock() * for more info. * * Returns 1 if entire region is locked, 0 if any portion is unlocked, and * negative on errors. */ static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) { int ret; ret = spi_nor_read_sr(nor, nor->bouncebuf); if (ret) return ret; return spi_nor_is_locked_sr(nor, ofs, len, nor->bouncebuf[0]); } static const struct spi_nor_locking_ops spi_nor_sr_locking_ops = { .lock = spi_nor_sr_lock, .unlock = spi_nor_sr_unlock, .is_locked = spi_nor_sr_is_locked, }; static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct spi_nor *nor = mtd_to_spi_nor(mtd); int ret; ret = spi_nor_lock_and_prep(nor); if (ret) return ret; ret = nor->params.locking_ops->lock(nor, ofs, len); spi_nor_unlock_and_unprep(nor); return ret; } static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct spi_nor *nor = mtd_to_spi_nor(mtd); int ret; ret = spi_nor_lock_and_prep(nor); if (ret) return ret; ret = nor->params.locking_ops->unlock(nor, ofs, len); spi_nor_unlock_and_unprep(nor); return ret; } static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct spi_nor *nor = mtd_to_spi_nor(mtd); int ret; ret = spi_nor_lock_and_prep(nor); if (ret) return ret; ret = nor->params.locking_ops->is_locked(nor, ofs, len); spi_nor_unlock_and_unprep(nor); return ret; } /** * spi_nor_sr1_bit6_quad_enable() - Set the Quad Enable BIT(6) in the Status * Register 1. * @nor: pointer to a 'struct spi_nor' * * Bit 6 of the Status Register 1 is the QE bit for Macronix like QSPI memories. * * Return: 0 on success, -errno otherwise. */ int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor) { int ret; ret = spi_nor_read_sr(nor, nor->bouncebuf); if (ret) return ret; if (nor->bouncebuf[0] & SR1_QUAD_EN_BIT6) return 0; nor->bouncebuf[0] |= SR1_QUAD_EN_BIT6; return spi_nor_write_sr1_and_check(nor, nor->bouncebuf[0]); } /** * spi_nor_sr2_bit1_quad_enable() - set the Quad Enable BIT(1) in the Status * Register 2. * @nor: pointer to a 'struct spi_nor'. * * Bit 1 of the Status Register 2 is the QE bit for Spansion like QSPI memories. * * Return: 0 on success, -errno otherwise. */ int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor) { int ret; if (nor->flags & SNOR_F_NO_READ_CR) return spi_nor_write_16bit_cr_and_check(nor, SR2_QUAD_EN_BIT1); ret = spi_nor_read_cr(nor, nor->bouncebuf); if (ret) return ret; if (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1) return 0; nor->bouncebuf[0] |= SR2_QUAD_EN_BIT1; return spi_nor_write_16bit_cr_and_check(nor, nor->bouncebuf[0]); } /** * spi_nor_sr2_bit7_quad_enable() - set QE bit in Status Register 2. * @nor: pointer to a 'struct spi_nor' * * Set the Quad Enable (QE) bit in the Status Register 2. * * This is one of the procedures to set the QE bit described in the SFDP * (JESD216 rev B) specification but no manufacturer using this procedure has * been identified yet, hence the name of the function. * * Return: 0 on success, -errno otherwise. */ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor) { u8 *sr2 = nor->bouncebuf; int ret; u8 sr2_written; /* Check current Quad Enable bit value. */ ret = spi_nor_read_sr2(nor, sr2); if (ret) return ret; if (*sr2 & SR2_QUAD_EN_BIT7) return 0; /* Update the Quad Enable bit. */ *sr2 |= SR2_QUAD_EN_BIT7; ret = spi_nor_write_sr2(nor, sr2); if (ret) return ret; sr2_written = *sr2; /* Read back and check it. */ ret = spi_nor_read_sr2(nor, sr2); if (ret) return ret; if (*sr2 != sr2_written) { dev_dbg(nor->dev, "SR2: Read back test failed\n"); return -EIO; } return 0; } static int is25lp256_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header, const struct sfdp_bfpt *bfpt, struct spi_nor_flash_parameter *params) { /* * IS25LP256 supports 4B opcodes, but the BFPT advertises a * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY address width. * Overwrite the address width advertised by the BFPT. */ if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) == BFPT_DWORD1_ADDRESS_BYTES_3_ONLY) nor->addr_width = 4; return 0; } static struct spi_nor_fixups is25lp256_fixups = { .post_bfpt = is25lp256_post_bfpt_fixups, }; static int mx25l25635_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header, const struct sfdp_bfpt *bfpt, struct spi_nor_flash_parameter *params) { /* * MX25L25635F supports 4B opcodes but MX25L25635E does not. * Unfortunately, Macronix has re-used the same JEDEC ID for both * variants which prevents us from defining a new entry in the parts * table. * We need a way to differentiate MX25L25635E and MX25L25635F, and it * seems that the F version advertises support for Fast Read 4-4-4 in * its BFPT table. */ if (bfpt->dwords[BFPT_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4) nor->flags |= SNOR_F_4B_OPCODES; return 0; } static struct spi_nor_fixups mx25l25635_fixups = { .post_bfpt = mx25l25635_post_bfpt_fixups, }; static void gd25q256_default_init(struct spi_nor *nor) { /* * Some manufacturer like GigaDevice may use different * bit to set QE on different memories, so the MFR can't * indicate the quad_enable method for this case, we need * to set it in the default_init fixup hook. */ nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable; } static struct spi_nor_fixups gd25q256_fixups = { .default_init = gd25q256_default_init, }; /* NOTE: double check command sets and memory organization when you add * more nor chips. This current list focusses on newer chips, which * have been converging on command sets which including JEDEC ID. * * All newly added entries should describe *hardware* and should use SECT_4K * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage * scenarios excluding small sectors there is config option that can be * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS. * For historical (and compatibility) reasons (before we got above config) some * old entries may be missing 4K flag. */ static const struct flash_info spi_nor_ids[] = { /* ESMT */ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, { "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, { "f25l64qa", INFO(0x8c4117, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_LOCK) }, /* Everspin */ { "mr25h128", CAT25_INFO( 16 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "mr25h40", CAT25_INFO(512 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, /* Fujitsu */ { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) }, /* GigaDevice */ { "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "gd25lq32", INFO(0xc86016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "gd25lq64c", INFO(0xc86017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "gd25lq128d", INFO(0xc86018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6) .fixups = &gd25q256_fixups, }, /* Intel/Numonyx -- xxxs33b */ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, /* ISSI */ { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp016d", INFO(0x9d6015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp080d", INFO(0x9d6014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp032", INFO(0x9d6016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ) }, { "is25lp064", INFO(0x9d6017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ) }, { "is25lp128", INFO(0x9d6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ) }, { "is25lp256", INFO(0x9d6019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) .fixups = &is25lp256_fixups }, { "is25wp032", INFO(0x9d7016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25wp064", INFO(0x9d7017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25wp128", INFO(0x9d7018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) .fixups = &is25lp256_fixups }, /* Macronix */ { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) }, { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) }, { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) }, { "mx25u2033e", INFO(0xc22532, 0, 64 * 1024, 4, SECT_4K) }, { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25u4035", INFO(0xc22533, 0, 64 * 1024, 8, SECT_4K) }, { "mx25u8035", INFO(0xc22534, 0, 64 * 1024, 16, SECT_4K) }, { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, { "mx25r3235f", INFO(0xc22816, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) .fixups = &mx25l25635_fixups }, { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, { "mx25v8035f", INFO(0xc22314, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "mx66l1g45g", INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, /* Micron <--> ST Micro */ { "n25q016a", INFO(0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) }, { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "mt25ql256a", INFO6(0x20ba19, 0x104400, 64 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "mt25qu256a", INFO6(0x20bb19, 0x104400, 64 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "n25q256ax1", INFO(0x20bb19, 0, 64 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "mt25ql512a", INFO6(0x20ba20, 0x104400, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "mt25qu512a", INFO6(0x20bb20, 0x104400, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { "mt25ql02g", INFO(0x20ba22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { "mt25qu02g", INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, /* Micron */ { "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512, SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, { "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) }, /* PMC */ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) }, { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) }, /* Spansion/Cypress -- single (large) sector size only, at least * for the chips listed here (without boot sectors). */ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) }, { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s25fl512s", INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | USE_CLSR) }, { "s25fs512s", INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) }, { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) }, { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) }, { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) }, { "s25fl208k", INFO(0x014014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ) }, { "s25fl064l", INFO(0x016017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "s25fl128l", INFO(0x016018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "s25fl256l", INFO(0x016019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, /* SST -- large erase sizes are "overlays", "sectors" are 4K */ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) }, { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) }, { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) }, { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) }, { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) }, { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) }, { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, { "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ) }, { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, /* ST Microelectronics -- newer production may have feature updates */ { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) }, { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) }, { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) }, { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) }, { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) }, { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) }, { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) }, { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) }, { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) }, { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) }, { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4, 0) }, { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K) }, { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) }, { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) }, { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) }, { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) }, /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) }, { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, { "w25q16dw", INFO(0xef6015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, { "w25q16jv-im/jm", INFO(0xef7015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "w25q20cl", INFO(0xef4012, 0, 64 * 1024, 4, SECT_4K) }, { "w25q20bw", INFO(0xef5012, 0, 64 * 1024, 4, SECT_4K) }, { "w25q20ew", INFO(0xef6012, 0, 64 * 1024, 4, SECT_4K) }, { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "w25q32jv", INFO(0xef7016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "w25q32jwm", INFO(0xef8016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "w25q128jv", INFO(0xef7018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, /* Catalyst / On Semiconductor -- non-JEDEC */ { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25c03", CAT25_INFO( 32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, /* Xilinx S3AN Internal Flash */ { "3S50AN", S3AN_INFO(0x1f2200, 64, 264) }, { "3S200AN", S3AN_INFO(0x1f2400, 256, 264) }, { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) }, { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) }, { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) }, /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { }, }; static const struct spi_nor_manufacturer *manufacturers[] = { &spi_nor_atmel, &spi_nor_eon, }; static const struct flash_info * spi_nor_search_part_by_id(const struct flash_info *parts, unsigned int nparts, const u8 *id) { unsigned int i; for (i = 0; i < nparts; i++) { if (parts[i].id_len && !memcmp(parts[i].id, id, parts[i].id_len)) return &parts[i]; } return NULL; } static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) { const struct flash_info *info; u8 *id = nor->bouncebuf; unsigned int i; int ret; if (nor->spimem) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1), SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(SPI_NOR_MAX_ID_LEN, id, 1)); ret = spi_mem_exec_op(nor->spimem, &op); } else { ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); } if (ret) { dev_dbg(nor->dev, "error %d reading JEDEC ID\n", ret); return ERR_PTR(ret); } for (i = 0; i < ARRAY_SIZE(manufacturers); i++) { info = spi_nor_search_part_by_id(manufacturers[i]->parts, manufacturers[i]->nparts, id); if (info) { nor->manufacturer = manufacturers[i]; return info; } } info = spi_nor_search_part_by_id(spi_nor_ids, ARRAY_SIZE(spi_nor_ids) - 1, id); if (info) return info; dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n", SPI_NOR_MAX_ID_LEN, id); return ERR_PTR(-ENODEV); } static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { struct spi_nor *nor = mtd_to_spi_nor(mtd); ssize_t ret; dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); ret = spi_nor_lock_and_prep(nor); if (ret) return ret; while (len) { loff_t addr = from; addr = spi_nor_convert_addr(nor, addr); ret = spi_nor_read_data(nor, addr, len, buf); if (ret == 0) { /* We shouldn't see 0-length reads */ ret = -EIO; goto read_err; } if (ret < 0) goto read_err; WARN_ON(ret > len); *retlen += ret; buf += ret; from += ret; len -= ret; } ret = 0; read_err: spi_nor_unlock_and_unprep(nor); return ret; } static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct spi_nor *nor = mtd_to_spi_nor(mtd); size_t actual = 0; int ret; dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); ret = spi_nor_lock_and_prep(nor); if (ret) return ret; ret = spi_nor_write_enable(nor); if (ret) goto out; nor->sst_write_second = false; /* Start write from odd address. */ if (to % 2) { nor->program_opcode = SPINOR_OP_BP; /* write one byte. */ ret = spi_nor_write_data(nor, to, 1, buf); if (ret < 0) goto out; WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret); ret = spi_nor_wait_till_ready(nor); if (ret) goto out; to++; actual++; } /* Write out most of the data here. */ for (; actual < len - 1; actual += 2) { nor->program_opcode = SPINOR_OP_AAI_WP; /* write two bytes. */ ret = spi_nor_write_data(nor, to, 2, buf + actual); if (ret < 0) goto out; WARN(ret != 2, "While writing 2 bytes written %i bytes\n", ret); ret = spi_nor_wait_till_ready(nor); if (ret) goto out; to += 2; nor->sst_write_second = true; } nor->sst_write_second = false; ret = spi_nor_write_disable(nor); if (ret) goto out; ret = spi_nor_wait_till_ready(nor); if (ret) goto out; /* Write out trailing byte if it exists. */ if (actual != len) { ret = spi_nor_write_enable(nor); if (ret) goto out; nor->program_opcode = SPINOR_OP_BP; ret = spi_nor_write_data(nor, to, 1, buf + actual); if (ret < 0) goto out; WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret); ret = spi_nor_wait_till_ready(nor); if (ret) goto out; actual += 1; ret = spi_nor_write_disable(nor); } out: *retlen += actual; spi_nor_unlock_and_unprep(nor); return ret; } /* * Write an address range to the nor chip. Data must be written in * FLASH_PAGESIZE chunks. The address range may be any size provided * it is within the physical boundaries. */ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct spi_nor *nor = mtd_to_spi_nor(mtd); size_t page_offset, page_remain, i; ssize_t ret; dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); ret = spi_nor_lock_and_prep(nor); if (ret) return ret; for (i = 0; i < len; ) { ssize_t written; loff_t addr = to + i; /* * If page_size is a power of two, the offset can be quickly * calculated with an AND operation. On the other cases we * need to do a modulus operation (more expensive). * Power of two numbers have only one bit set and we can use * the instruction hweight32 to detect if we need to do a * modulus (do_div()) or not. */ if (hweight32(nor->page_size) == 1) { page_offset = addr & (nor->page_size - 1); } else { uint64_t aux = addr; page_offset = do_div(aux, nor->page_size); } /* the size of data remaining on the first page */ page_remain = min_t(size_t, nor->page_size - page_offset, len - i); addr = spi_nor_convert_addr(nor, addr); ret = spi_nor_write_enable(nor); if (ret) goto write_err; ret = spi_nor_write_data(nor, addr, page_remain, buf + i); if (ret < 0) goto write_err; written = ret; ret = spi_nor_wait_till_ready(nor); if (ret) goto write_err; *retlen += written; i += written; } write_err: spi_nor_unlock_and_unprep(nor); return ret; } static int spi_nor_check(struct spi_nor *nor) { if (!nor->dev || (!nor->spimem && !nor->controller_ops) || (!nor->spimem && nor->controller_ops && (!nor->controller_ops->read || !nor->controller_ops->write || !nor->controller_ops->read_reg || !nor->controller_ops->write_reg))) { pr_err("spi-nor: please fill all the necessary fields!\n"); return -EINVAL; } if (nor->spimem && nor->controller_ops) { dev_err(nor->dev, "nor->spimem and nor->controller_ops are mutually exclusive, please set just one of them.\n"); return -EINVAL; } return 0; } static int s3an_nor_setup(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps) { int ret; ret = spi_nor_xread_sr(nor, nor->bouncebuf); if (ret) return ret; nor->erase_opcode = SPINOR_OP_XSE; nor->program_opcode = SPINOR_OP_XPP; nor->read_opcode = SPINOR_OP_READ; nor->flags |= SNOR_F_NO_OP_CHIP_ERASE; /* * This flashes have a page size of 264 or 528 bytes (known as * Default addressing mode). It can be changed to a more standard * Power of two mode where the page size is 256/512. This comes * with a price: there is 3% less of space, the data is corrupted * and the page size cannot be changed back to default addressing * mode. * * The current addressing mode can be read from the XRDSR register * and should not be changed, because is a destructive operation. */ if (nor->bouncebuf[0] & XSR_PAGESIZE) { /* Flash in Power of 2 mode */ nor->page_size = (nor->page_size == 264) ? 256 : 512; nor->mtd.writebufsize = nor->page_size; nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors; nor->mtd.erasesize = 8 * nor->page_size; } else { /* Flash in Default addressing mode */ nor->params.convert_addr = s3an_convert_addr; nor->mtd.erasesize = nor->info->sector_size; } return 0; } static void spi_nor_set_read_settings(struct spi_nor_read_command *read, u8 num_mode_clocks, u8 num_wait_states, u8 opcode, enum spi_nor_protocol proto) { read->num_mode_clocks = num_mode_clocks; read->num_wait_states = num_wait_states; read->opcode = opcode; read->proto = proto; } void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode, enum spi_nor_protocol proto) { pp->opcode = opcode; pp->proto = proto; } static int spi_nor_hwcaps2cmd(u32 hwcaps, const int table[][2], size_t size) { size_t i; for (i = 0; i < size; i++) if (table[i][0] == (int)hwcaps) return table[i][1]; return -EINVAL; } int spi_nor_hwcaps_read2cmd(u32 hwcaps) { static const int hwcaps_read2cmd[][2] = { { SNOR_HWCAPS_READ, SNOR_CMD_READ }, { SNOR_HWCAPS_READ_FAST, SNOR_CMD_READ_FAST }, { SNOR_HWCAPS_READ_1_1_1_DTR, SNOR_CMD_READ_1_1_1_DTR }, { SNOR_HWCAPS_READ_1_1_2, SNOR_CMD_READ_1_1_2 }, { SNOR_HWCAPS_READ_1_2_2, SNOR_CMD_READ_1_2_2 }, { SNOR_HWCAPS_READ_2_2_2, SNOR_CMD_READ_2_2_2 }, { SNOR_HWCAPS_READ_1_2_2_DTR, SNOR_CMD_READ_1_2_2_DTR }, { SNOR_HWCAPS_READ_1_1_4, SNOR_CMD_READ_1_1_4 }, { SNOR_HWCAPS_READ_1_4_4, SNOR_CMD_READ_1_4_4 }, { SNOR_HWCAPS_READ_4_4_4, SNOR_CMD_READ_4_4_4 }, { SNOR_HWCAPS_READ_1_4_4_DTR, SNOR_CMD_READ_1_4_4_DTR }, { SNOR_HWCAPS_READ_1_1_8, SNOR_CMD_READ_1_1_8 }, { SNOR_HWCAPS_READ_1_8_8, SNOR_CMD_READ_1_8_8 }, { SNOR_HWCAPS_READ_8_8_8, SNOR_CMD_READ_8_8_8 }, { SNOR_HWCAPS_READ_1_8_8_DTR, SNOR_CMD_READ_1_8_8_DTR }, }; return spi_nor_hwcaps2cmd(hwcaps, hwcaps_read2cmd, ARRAY_SIZE(hwcaps_read2cmd)); } static int spi_nor_hwcaps_pp2cmd(u32 hwcaps) { static const int hwcaps_pp2cmd[][2] = { { SNOR_HWCAPS_PP, SNOR_CMD_PP }, { SNOR_HWCAPS_PP_1_1_4, SNOR_CMD_PP_1_1_4 }, { SNOR_HWCAPS_PP_1_4_4, SNOR_CMD_PP_1_4_4 }, { SNOR_HWCAPS_PP_4_4_4, SNOR_CMD_PP_4_4_4 }, { SNOR_HWCAPS_PP_1_1_8, SNOR_CMD_PP_1_1_8 }, { SNOR_HWCAPS_PP_1_8_8, SNOR_CMD_PP_1_8_8 }, { SNOR_HWCAPS_PP_8_8_8, SNOR_CMD_PP_8_8_8 }, }; return spi_nor_hwcaps2cmd(hwcaps, hwcaps_pp2cmd, ARRAY_SIZE(hwcaps_pp2cmd)); } /** * spi_nor_spimem_check_op - check if the operation is supported * by controller *@nor: pointer to a 'struct spi_nor' *@op: pointer to op template to be checked * * Returns 0 if operation is supported, -ENOTSUPP otherwise. */ static int spi_nor_spimem_check_op(struct spi_nor *nor, struct spi_mem_op *op) { /* * First test with 4 address bytes. The opcode itself might * be a 3B addressing opcode but we don't care, because * SPI controller implementation should not check the opcode, * but just the sequence. */ op->addr.nbytes = 4; if (!spi_mem_supports_op(nor->spimem, op)) { if (nor->mtd.size > SZ_16M) return -ENOTSUPP; /* If flash size <= 16MB, 3 address bytes are sufficient */ op->addr.nbytes = 3; if (!spi_mem_supports_op(nor->spimem, op)) return -ENOTSUPP; } return 0; } /** * spi_nor_spimem_check_readop - check if the read op is supported * by controller *@nor: pointer to a 'struct spi_nor' *@read: pointer to op template to be checked * * Returns 0 if operation is supported, -ENOTSUPP otherwise. */ static int spi_nor_spimem_check_readop(struct spi_nor *nor, const struct spi_nor_read_command *read) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(read->opcode, 1), SPI_MEM_OP_ADDR(3, 0, 1), SPI_MEM_OP_DUMMY(0, 1), SPI_MEM_OP_DATA_IN(0, NULL, 1)); op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(read->proto); op.addr.buswidth = spi_nor_get_protocol_addr_nbits(read->proto); op.data.buswidth = spi_nor_get_protocol_data_nbits(read->proto); op.dummy.buswidth = op.addr.buswidth; op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) * op.dummy.buswidth / 8; return spi_nor_spimem_check_op(nor, &op); } /** * spi_nor_spimem_check_pp - check if the page program op is supported * by controller *@nor: pointer to a 'struct spi_nor' *@pp: pointer to op template to be checked * * Returns 0 if operation is supported, -ENOTSUPP otherwise. */ static int spi_nor_spimem_check_pp(struct spi_nor *nor, const struct spi_nor_pp_command *pp) { struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(pp->opcode, 1), SPI_MEM_OP_ADDR(3, 0, 1), SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(0, NULL, 1)); op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(pp->proto); op.addr.buswidth = spi_nor_get_protocol_addr_nbits(pp->proto); op.data.buswidth = spi_nor_get_protocol_data_nbits(pp->proto); return spi_nor_spimem_check_op(nor, &op); } /** * spi_nor_spimem_adjust_hwcaps - Find optimal Read/Write protocol * based on SPI controller capabilities * @nor: pointer to a 'struct spi_nor' * @hwcaps: pointer to resulting capabilities after adjusting * according to controller and flash's capability */ static void spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps) { struct spi_nor_flash_parameter *params = &nor->params; unsigned int cap; /* DTR modes are not supported yet, mask them all. */ *hwcaps &= ~SNOR_HWCAPS_DTR; /* X-X-X modes are not supported yet, mask them all. */ *hwcaps &= ~SNOR_HWCAPS_X_X_X; for (cap = 0; cap < sizeof(*hwcaps) * BITS_PER_BYTE; cap++) { int rdidx, ppidx; if (!(*hwcaps & BIT(cap))) continue; rdidx = spi_nor_hwcaps_read2cmd(BIT(cap)); if (rdidx >= 0 && spi_nor_spimem_check_readop(nor, ¶ms->reads[rdidx])) *hwcaps &= ~BIT(cap); ppidx = spi_nor_hwcaps_pp2cmd(BIT(cap)); if (ppidx < 0) continue; if (spi_nor_spimem_check_pp(nor, ¶ms->page_programs[ppidx])) *hwcaps &= ~BIT(cap); } } /** * spi_nor_set_erase_type() - set a SPI NOR erase type * @erase: pointer to a structure that describes a SPI NOR erase type * @size: the size of the sector/block erased by the erase type * @opcode: the SPI command op code to erase the sector/block */ void spi_nor_set_erase_type(struct spi_nor_erase_type *erase, u32 size, u8 opcode) { erase->size = size; erase->opcode = opcode; /* JEDEC JESD216B Standard imposes erase sizes to be power of 2. */ erase->size_shift = ffs(erase->size) - 1; erase->size_mask = (1 << erase->size_shift) - 1; } /** * spi_nor_init_uniform_erase_map() - Initialize uniform erase map * @map: the erase map of the SPI NOR * @erase_mask: bitmask encoding erase types that can erase the entire * flash memory * @flash_size: the spi nor flash memory size */ void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map, u8 erase_mask, u64 flash_size) { /* Offset 0 with erase_mask and SNOR_LAST_REGION bit set */ map->uniform_region.offset = (erase_mask & SNOR_ERASE_TYPE_MASK) | SNOR_LAST_REGION; map->uniform_region.size = flash_size; map->regions = &map->uniform_region; map->uniform_erase_type = erase_mask; } int spi_nor_post_bfpt_fixups(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header, const struct sfdp_bfpt *bfpt, struct spi_nor_flash_parameter *params) { int ret; if (nor->manufacturer && nor->manufacturer->fixups && nor->manufacturer->fixups->post_bfpt) { ret = nor->manufacturer->fixups->post_bfpt(nor, bfpt_header, bfpt, params); if (ret) return ret; } if (nor->info->fixups && nor->info->fixups->post_bfpt) return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt, params); return 0; } static int spi_nor_select_read(struct spi_nor *nor, u32 shared_hwcaps) { int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_READ_MASK) - 1; const struct spi_nor_read_command *read; if (best_match < 0) return -EINVAL; cmd = spi_nor_hwcaps_read2cmd(BIT(best_match)); if (cmd < 0) return -EINVAL; read = &nor->params.reads[cmd]; nor->read_opcode = read->opcode; nor->read_proto = read->proto; /* * In the spi-nor framework, we don't need to make the difference * between mode clock cycles and wait state clock cycles. * Indeed, the value of the mode clock cycles is used by a QSPI * flash memory to know whether it should enter or leave its 0-4-4 * (Continuous Read / XIP) mode. * eXecution In Place is out of the scope of the mtd sub-system. * Hence we choose to merge both mode and wait state clock cycles * into the so called dummy clock cycles. */ nor->read_dummy = read->num_mode_clocks + read->num_wait_states; return 0; } static int spi_nor_select_pp(struct spi_nor *nor, u32 shared_hwcaps) { int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_PP_MASK) - 1; const struct spi_nor_pp_command *pp; if (best_match < 0) return -EINVAL; cmd = spi_nor_hwcaps_pp2cmd(BIT(best_match)); if (cmd < 0) return -EINVAL; pp = &nor->params.page_programs[cmd]; nor->program_opcode = pp->opcode; nor->write_proto = pp->proto; return 0; } /** * spi_nor_select_uniform_erase() - select optimum uniform erase type * @map: the erase map of the SPI NOR * @wanted_size: the erase type size to search for. Contains the value of * info->sector_size or of the "small sector" size in case * CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is defined. * * Once the optimum uniform sector erase command is found, disable all the * other. * * Return: pointer to erase type on success, NULL otherwise. */ static const struct spi_nor_erase_type * spi_nor_select_uniform_erase(struct spi_nor_erase_map *map, const u32 wanted_size) { const struct spi_nor_erase_type *tested_erase, *erase = NULL; int i; u8 uniform_erase_type = map->uniform_erase_type; for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { if (!(uniform_erase_type & BIT(i))) continue; tested_erase = &map->erase_type[i]; /* * If the current erase size is the one, stop here: * we have found the right uniform Sector Erase command. */ if (tested_erase->size == wanted_size) { erase = tested_erase; break; } /* * Otherwise, the current erase size is still a valid canditate. * Select the biggest valid candidate. */ if (!erase && tested_erase->size) erase = tested_erase; /* keep iterating to find the wanted_size */ } if (!erase) return NULL; /* Disable all other Sector Erase commands. */ map->uniform_erase_type &= ~SNOR_ERASE_TYPE_MASK; map->uniform_erase_type |= BIT(erase - map->erase_type); return erase; } static int spi_nor_select_erase(struct spi_nor *nor) { struct spi_nor_erase_map *map = &nor->params.erase_map; const struct spi_nor_erase_type *erase = NULL; struct mtd_info *mtd = &nor->mtd; u32 wanted_size = nor->info->sector_size; int i; /* * The previous implementation handling Sector Erase commands assumed * that the SPI flash memory has an uniform layout then used only one * of the supported erase sizes for all Sector Erase commands. * So to be backward compatible, the new implementation also tries to * manage the SPI flash memory as uniform with a single erase sector * size, when possible. */ #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS /* prefer "small sector" erase if possible */ wanted_size = 4096u; #endif if (spi_nor_has_uniform_erase(nor)) { erase = spi_nor_select_uniform_erase(map, wanted_size); if (!erase) return -EINVAL; nor->erase_opcode = erase->opcode; mtd->erasesize = erase->size; return 0; } /* * For non-uniform SPI flash memory, set mtd->erasesize to the * maximum erase sector size. No need to set nor->erase_opcode. */ for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) { if (map->erase_type[i].size) { erase = &map->erase_type[i]; break; } } if (!erase) return -EINVAL; mtd->erasesize = erase->size; return 0; } static int spi_nor_default_setup(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps) { struct spi_nor_flash_parameter *params = &nor->params; u32 ignored_mask, shared_mask; int err; /* * Keep only the hardware capabilities supported by both the SPI * controller and the SPI flash memory. */ shared_mask = hwcaps->mask & params->hwcaps.mask; if (nor->spimem) { /* * When called from spi_nor_probe(), all caps are set and we * need to discard some of them based on what the SPI * controller actually supports (using spi_mem_supports_op()). */ spi_nor_spimem_adjust_hwcaps(nor, &shared_mask); } else { /* * SPI n-n-n protocols are not supported when the SPI * controller directly implements the spi_nor interface. * Yet another reason to switch to spi-mem. */ ignored_mask = SNOR_HWCAPS_X_X_X; if (shared_mask & ignored_mask) { dev_dbg(nor->dev, "SPI n-n-n protocols are not supported.\n"); shared_mask &= ~ignored_mask; } } /* Select the (Fast) Read command. */ err = spi_nor_select_read(nor, shared_mask); if (err) { dev_dbg(nor->dev, "can't select read settings supported by both the SPI controller and memory.\n"); return err; } /* Select the Page Program command. */ err = spi_nor_select_pp(nor, shared_mask); if (err) { dev_dbg(nor->dev, "can't select write settings supported by both the SPI controller and memory.\n"); return err; } /* Select the Sector Erase command. */ err = spi_nor_select_erase(nor); if (err) { dev_dbg(nor->dev, "can't select erase settings supported by both the SPI controller and memory.\n"); return err; } return 0; } static int spi_nor_setup(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps) { if (!nor->params.setup) return 0; return nor->params.setup(nor, hwcaps); } static void intel_set_default_init(struct spi_nor *nor) { nor->flags |= SNOR_F_HAS_LOCK; } static void issi_set_default_init(struct spi_nor *nor) { nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable; } static void macronix_set_default_init(struct spi_nor *nor) { nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable; nor->params.set_4byte_addr_mode = spi_nor_set_4byte_addr_mode; } static void sst_set_default_init(struct spi_nor *nor) { nor->flags |= SNOR_F_HAS_LOCK; } static void st_micron_set_default_init(struct spi_nor *nor) { nor->flags |= SNOR_F_HAS_LOCK; nor->flags &= ~SNOR_F_HAS_16BIT_SR; nor->params.quad_enable = NULL; nor->params.set_4byte_addr_mode = st_micron_set_4byte_addr_mode; } static void winbond_set_default_init(struct spi_nor *nor) { nor->params.set_4byte_addr_mode = winbond_set_4byte_addr_mode; } /** * spi_nor_manufacturer_init_params() - Initialize the flash's parameters and * settings based on MFR register and ->default_init() hook. * @nor: pointer to a 'struct spi-nor'. */ static void spi_nor_manufacturer_init_params(struct spi_nor *nor) { /* Init flash parameters based on MFR */ switch (JEDEC_MFR(nor->info)) { case SNOR_MFR_INTEL: intel_set_default_init(nor); break; case SNOR_MFR_ISSI: issi_set_default_init(nor); break; case SNOR_MFR_MACRONIX: macronix_set_default_init(nor); break; case SNOR_MFR_ST: case SNOR_MFR_MICRON: st_micron_set_default_init(nor); break; case SNOR_MFR_SST: sst_set_default_init(nor); break; case SNOR_MFR_WINBOND: winbond_set_default_init(nor); break; default: break; } if (nor->manufacturer && nor->manufacturer->fixups && nor->manufacturer->fixups->default_init) nor->manufacturer->fixups->default_init(nor); if (nor->info->fixups && nor->info->fixups->default_init) nor->info->fixups->default_init(nor); } /** * spi_nor_sfdp_init_params() - Initialize the flash's parameters and settings * based on JESD216 SFDP standard. * @nor: pointer to a 'struct spi-nor'. * * The method has a roll-back mechanism: in case the SFDP parsing fails, the * legacy flash parameters and settings will be restored. */ static void spi_nor_sfdp_init_params(struct spi_nor *nor) { struct spi_nor_flash_parameter sfdp_params; memcpy(&sfdp_params, &nor->params, sizeof(sfdp_params)); if (spi_nor_parse_sfdp(nor, &sfdp_params)) { nor->addr_width = 0; nor->flags &= ~SNOR_F_4B_OPCODES; } else { memcpy(&nor->params, &sfdp_params, sizeof(nor->params)); } } /** * spi_nor_info_init_params() - Initialize the flash's parameters and settings * based on nor->info data. * @nor: pointer to a 'struct spi-nor'. */ static void spi_nor_info_init_params(struct spi_nor *nor) { struct spi_nor_flash_parameter *params = &nor->params; struct spi_nor_erase_map *map = ¶ms->erase_map; const struct flash_info *info = nor->info; struct device_node *np = spi_nor_get_flash_node(nor); u8 i, erase_mask; /* Initialize legacy flash parameters and settings. */ params->quad_enable = spi_nor_sr2_bit1_quad_enable; params->set_4byte_addr_mode = spansion_set_4byte_addr_mode; params->setup = spi_nor_default_setup; /* Default to 16-bit Write Status (01h) Command */ nor->flags |= SNOR_F_HAS_16BIT_SR; /* Set SPI NOR sizes. */ params->size = (u64)info->sector_size * info->n_sectors; params->page_size = info->page_size; if (!(info->flags & SPI_NOR_NO_FR)) { /* Default to Fast Read for DT and non-DT platform devices. */ params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST; /* Mask out Fast Read if not requested at DT instantiation. */ if (np && !of_property_read_bool(np, "m25p,fast-read")) params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST; } /* (Fast) Read settings. */ params->hwcaps.mask |= SNOR_HWCAPS_READ; spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ], 0, 0, SPINOR_OP_READ, SNOR_PROTO_1_1_1); if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST) spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_FAST], 0, 8, SPINOR_OP_READ_FAST, SNOR_PROTO_1_1_1); if (info->flags & SPI_NOR_DUAL_READ) { params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2; spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_2], 0, 8, SPINOR_OP_READ_1_1_2, SNOR_PROTO_1_1_2); } if (info->flags & SPI_NOR_QUAD_READ) { params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4; spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_4], 0, 8, SPINOR_OP_READ_1_1_4, SNOR_PROTO_1_1_4); } if (info->flags & SPI_NOR_OCTAL_READ) { params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8; spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_8], 0, 8, SPINOR_OP_READ_1_1_8, SNOR_PROTO_1_1_8); } /* Page Program settings. */ params->hwcaps.mask |= SNOR_HWCAPS_PP; spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP], SPINOR_OP_PP, SNOR_PROTO_1_1_1); /* * Sector Erase settings. Sort Erase Types in ascending order, with the * smallest erase size starting at BIT(0). */ erase_mask = 0; i = 0; if (info->flags & SECT_4K_PMC) { erase_mask |= BIT(i); spi_nor_set_erase_type(&map->erase_type[i], 4096u, SPINOR_OP_BE_4K_PMC); i++; } else if (info->flags & SECT_4K) { erase_mask |= BIT(i); spi_nor_set_erase_type(&map->erase_type[i], 4096u, SPINOR_OP_BE_4K); i++; } erase_mask |= BIT(i); spi_nor_set_erase_type(&map->erase_type[i], info->sector_size, SPINOR_OP_SE); spi_nor_init_uniform_erase_map(map, erase_mask, params->size); } static void spansion_post_sfdp_fixups(struct spi_nor *nor) { if (nor->params.size <= SZ_16M) return; nor->flags |= SNOR_F_4B_OPCODES; /* No small sector erase for 4-byte command set */ nor->erase_opcode = SPINOR_OP_SE; nor->mtd.erasesize = nor->info->sector_size; } static void s3an_post_sfdp_fixups(struct spi_nor *nor) { nor->params.setup = s3an_nor_setup; } /** * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings * after SFDP has been parsed (is also called for SPI NORs that do not * support RDSFDP). * @nor: pointer to a 'struct spi_nor' * * Typically used to tweak various parameters that could not be extracted by * other means (i.e. when information provided by the SFDP/flash_info tables * are incomplete or wrong). */ static void spi_nor_post_sfdp_fixups(struct spi_nor *nor) { switch (JEDEC_MFR(nor->info)) { case SNOR_MFR_SPANSION: spansion_post_sfdp_fixups(nor); break; default: break; } if (nor->info->flags & SPI_S3AN) s3an_post_sfdp_fixups(nor); if (nor->manufacturer && nor->manufacturer->fixups && nor->manufacturer->fixups->post_sfdp) nor->manufacturer->fixups->post_sfdp(nor); if (nor->info->fixups && nor->info->fixups->post_sfdp) nor->info->fixups->post_sfdp(nor); } /** * spi_nor_late_init_params() - Late initialization of default flash parameters. * @nor: pointer to a 'struct spi_nor' * * Used to set default flash parameters and settings when the ->default_init() * hook or the SFDP parser let voids. */ static void spi_nor_late_init_params(struct spi_nor *nor) { /* * NOR protection support. When locking_ops are not provided, we pick * the default ones. */ if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops) nor->params.locking_ops = &spi_nor_sr_locking_ops; } /** * spi_nor_init_params() - Initialize the flash's parameters and settings. * @nor: pointer to a 'struct spi-nor'. * * The flash parameters and settings are initialized based on a sequence of * calls that are ordered by priority: * * 1/ Default flash parameters initialization. The initializations are done * based on nor->info data: * spi_nor_info_init_params() * * which can be overwritten by: * 2/ Manufacturer flash parameters initialization. The initializations are * done based on MFR register, or when the decisions can not be done solely * based on MFR, by using specific flash_info tweeks, ->default_init(): * spi_nor_manufacturer_init_params() * * which can be overwritten by: * 3/ SFDP flash parameters initialization. JESD216 SFDP is a standard and * should be more accurate that the above. * spi_nor_sfdp_init_params() * * Please note that there is a ->post_bfpt() fixup hook that can overwrite * the flash parameters and settings immediately after parsing the Basic * Flash Parameter Table. * * which can be overwritten by: * 4/ Post SFDP flash parameters initialization. Used to tweak various * parameters that could not be extracted by other means (i.e. when * information provided by the SFDP/flash_info tables are incomplete or * wrong). * spi_nor_post_sfdp_fixups() * * 5/ Late default flash parameters initialization, used when the * ->default_init() hook or the SFDP parser do not set specific params. * spi_nor_late_init_params() */ static void spi_nor_init_params(struct spi_nor *nor) { spi_nor_info_init_params(nor); spi_nor_manufacturer_init_params(nor); if ((nor->info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) && !(nor->info->flags & SPI_NOR_SKIP_SFDP)) spi_nor_sfdp_init_params(nor); spi_nor_post_sfdp_fixups(nor); spi_nor_late_init_params(nor); } /** * spi_nor_quad_enable() - enable Quad I/O if needed. * @nor: pointer to a 'struct spi_nor' * * Return: 0 on success, -errno otherwise. */ static int spi_nor_quad_enable(struct spi_nor *nor) { if (!nor->params.quad_enable) return 0; if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 || spi_nor_get_protocol_width(nor->write_proto) == 4)) return 0; return nor->params.quad_enable(nor); } /** * spi_nor_unlock_all() - Unlocks the entire flash memory array. * @nor: pointer to a 'struct spi_nor'. * * Some SPI NOR flashes are write protected by default after a power-on reset * cycle, in order to avoid inadvertent writes during power-up. Backward * compatibility imposes to unlock the entire flash memory array at power-up * by default. */ static int spi_nor_unlock_all(struct spi_nor *nor) { if (nor->flags & SNOR_F_HAS_LOCK) return spi_nor_unlock(&nor->mtd, 0, nor->params.size); return 0; } static int spi_nor_init(struct spi_nor *nor) { int err; err = spi_nor_quad_enable(nor); if (err) { dev_dbg(nor->dev, "quad mode not supported\n"); return err; } err = spi_nor_unlock_all(nor); if (err) { dev_dbg(nor->dev, "Failed to unlock the entire flash memory array\n"); return err; } if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES)) { /* * If the RESET# pin isn't hooked up properly, or the system * otherwise doesn't perform a reset command in the boot * sequence, it's impossible to 100% protect against unexpected * reboots (e.g., crashes). Warn the user (or hopefully, system * designer) that this is bad. */ WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET, "enabling reset hack; may not recover from unexpected reboots\n"); nor->params.set_4byte_addr_mode(nor, true); } return 0; } /* mtd resume handler */ static void spi_nor_resume(struct mtd_info *mtd) { struct spi_nor *nor = mtd_to_spi_nor(mtd); struct device *dev = nor->dev; int ret; /* re-initialize the nor chip */ ret = spi_nor_init(nor); if (ret) dev_err(dev, "resume() failed\n"); } void spi_nor_restore(struct spi_nor *nor) { /* restore the addressing mode */ if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) && nor->flags & SNOR_F_BROKEN_RESET) nor->params.set_4byte_addr_mode(nor, false); } EXPORT_SYMBOL_GPL(spi_nor_restore); static const struct flash_info *spi_nor_match_id(struct spi_nor *nor, const char *name) { unsigned int i, j; for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) { if (!strcmp(name, spi_nor_ids[i].name)) return &spi_nor_ids[i]; } for (i = 0; i < ARRAY_SIZE(manufacturers); i++) { for (j = 0; j < manufacturers[i]->nparts; j++) { if (!strcmp(name, manufacturers[i]->parts[j].name)) { nor->manufacturer = manufacturers[i]; return &manufacturers[i]->parts[j]; } } } return NULL; } static int spi_nor_set_addr_width(struct spi_nor *nor) { if (nor->addr_width) { /* already configured from SFDP */ } else if (nor->info->addr_width) { nor->addr_width = nor->info->addr_width; } else if (nor->mtd.size > 0x1000000) { /* enable 4-byte addressing if the device exceeds 16MiB */ nor->addr_width = 4; } else { nor->addr_width = 3; } if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) { dev_dbg(nor->dev, "address width is too large: %u\n", nor->addr_width); return -EINVAL; } /* Set 4byte opcodes when possible. */ if (nor->addr_width == 4 && nor->flags & SNOR_F_4B_OPCODES && !(nor->flags & SNOR_F_HAS_4BAIT)) spi_nor_set_4byte_opcodes(nor); return 0; } static void spi_nor_debugfs_init(struct spi_nor *nor, const struct flash_info *info) { struct mtd_info *mtd = &nor->mtd; mtd->dbg.partname = info->name; mtd->dbg.partid = devm_kasprintf(nor->dev, GFP_KERNEL, "spi-nor:%*phN", info->id_len, info->id); } static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor, const char *name) { const struct flash_info *info = NULL; if (name) info = spi_nor_match_id(nor, name); /* Try to auto-detect if chip name wasn't specified or not found */ if (!info) info = spi_nor_read_id(nor); if (IS_ERR_OR_NULL(info)) return ERR_PTR(-ENOENT); /* * If caller has specified name of flash model that can normally be * detected using JEDEC, let's verify it. */ if (name && info->id_len) { const struct flash_info *jinfo; jinfo = spi_nor_read_id(nor); if (IS_ERR(jinfo)) { return jinfo; } else if (jinfo != info) { /* * JEDEC knows better, so overwrite platform ID. We * can't trust partitions any longer, but we'll let * mtd apply them anyway, since some partitions may be * marked read-only, and we don't want to lose that * information, even if it's not 100% accurate. */ dev_warn(nor->dev, "found %s, expected %s\n", jinfo->name, info->name); info = jinfo; } } return info; } int spi_nor_scan(struct spi_nor *nor, const char *name, const struct spi_nor_hwcaps *hwcaps) { const struct flash_info *info; struct device *dev = nor->dev; struct mtd_info *mtd = &nor->mtd; struct device_node *np = spi_nor_get_flash_node(nor); struct spi_nor_flash_parameter *params = &nor->params; int ret; int i; ret = spi_nor_check(nor); if (ret) return ret; /* Reset SPI protocol for all commands. */ nor->reg_proto = SNOR_PROTO_1_1_1; nor->read_proto = SNOR_PROTO_1_1_1; nor->write_proto = SNOR_PROTO_1_1_1; /* * We need the bounce buffer early to read/write registers when going * through the spi-mem layer (buffers have to be DMA-able). * For spi-mem drivers, we'll reallocate a new buffer if * nor->page_size turns out to be greater than PAGE_SIZE (which * shouldn't happen before long since NOR pages are usually less * than 1KB) after spi_nor_scan() returns. */ nor->bouncebuf_size = PAGE_SIZE; nor->bouncebuf = devm_kmalloc(dev, nor->bouncebuf_size, GFP_KERNEL); if (!nor->bouncebuf) return -ENOMEM; info = spi_nor_get_flash_info(nor, name); if (IS_ERR(info)) return PTR_ERR(info); nor->info = info; spi_nor_debugfs_init(nor, info); mutex_init(&nor->lock); /* * Make sure the XSR_RDY flag is set before calling * spi_nor_wait_till_ready(). Xilinx S3AN share MFR * with Atmel spi-nor */ if (info->flags & SPI_NOR_XSR_RDY) nor->flags |= SNOR_F_READY_XSR_RDY; if (info->flags & SPI_NOR_HAS_LOCK) nor->flags |= SNOR_F_HAS_LOCK; /* Init flash parameters based on flash_info struct and SFDP */ spi_nor_init_params(nor); if (!mtd->name) mtd->name = dev_name(dev); mtd->priv = nor; mtd->type = MTD_NORFLASH; mtd->writesize = 1; mtd->flags = MTD_CAP_NORFLASH; mtd->size = params->size; mtd->_erase = spi_nor_erase; mtd->_read = spi_nor_read; mtd->_resume = spi_nor_resume; if (nor->params.locking_ops) { mtd->_lock = spi_nor_lock; mtd->_unlock = spi_nor_unlock; mtd->_is_locked = spi_nor_is_locked; } /* sst nor chips use AAI word program */ if (info->flags & SST_WRITE) mtd->_write = sst_write; else mtd->_write = spi_nor_write; if (info->flags & USE_FSR) nor->flags |= SNOR_F_USE_FSR; if (info->flags & SPI_NOR_HAS_TB) { nor->flags |= SNOR_F_HAS_SR_TB; if (info->flags & SPI_NOR_TB_SR_BIT6) nor->flags |= SNOR_F_HAS_SR_TB_BIT6; } if (info->flags & NO_CHIP_ERASE) nor->flags |= SNOR_F_NO_OP_CHIP_ERASE; if (info->flags & USE_CLSR) nor->flags |= SNOR_F_USE_CLSR; if (info->flags & SPI_NOR_NO_ERASE) mtd->flags |= MTD_NO_ERASE; mtd->dev.parent = dev; nor->page_size = params->page_size; mtd->writebufsize = nor->page_size; if (of_property_read_bool(np, "broken-flash-reset")) nor->flags |= SNOR_F_BROKEN_RESET; /* * Configure the SPI memory: * - select op codes for (Fast) Read, Page Program and Sector Erase. * - set the number of dummy cycles (mode cycles + wait states). * - set the SPI protocols for register and memory accesses. */ ret = spi_nor_setup(nor, hwcaps); if (ret) return ret; if (info->flags & SPI_NOR_4B_OPCODES) nor->flags |= SNOR_F_4B_OPCODES; ret = spi_nor_set_addr_width(nor); if (ret) return ret; /* Send all the required SPI flash commands to initialize device */ ret = spi_nor_init(nor); if (ret) return ret; dev_info(dev, "%s (%lld Kbytes)\n", info->name, (long long)mtd->size >> 10); dev_dbg(dev, "mtd .name = %s, .size = 0x%llx (%lldMiB), " ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20), mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions); if (mtd->numeraseregions) for (i = 0; i < mtd->numeraseregions; i++) dev_dbg(dev, "mtd.eraseregions[%d] = { .offset = 0x%llx, " ".erasesize = 0x%.8x (%uKiB), " ".numblocks = %d }\n", i, (long long)mtd->eraseregions[i].offset, mtd->eraseregions[i].erasesize, mtd->eraseregions[i].erasesize / 1024, mtd->eraseregions[i].numblocks); return 0; } EXPORT_SYMBOL_GPL(spi_nor_scan); static int spi_nor_create_read_dirmap(struct spi_nor *nor) { struct spi_mem_dirmap_info info = { .op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1), SPI_MEM_OP_ADDR(nor->addr_width, 0, 1), SPI_MEM_OP_DUMMY(nor->read_dummy, 1), SPI_MEM_OP_DATA_IN(0, NULL, 1)), .offset = 0, .length = nor->mtd.size, }; struct spi_mem_op *op = &info.op_tmpl; /* get transfer protocols. */ op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); op->addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto); op->dummy.buswidth = op->addr.buswidth; op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto); /* convert the dummy cycles to the number of bytes */ op->dummy.nbytes = (nor->read_dummy * op->dummy.buswidth) / 8; nor->dirmap.rdesc = devm_spi_mem_dirmap_create(nor->dev, nor->spimem, &info); return PTR_ERR_OR_ZERO(nor->dirmap.rdesc); } static int spi_nor_create_write_dirmap(struct spi_nor *nor) { struct spi_mem_dirmap_info info = { .op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1), SPI_MEM_OP_ADDR(nor->addr_width, 0, 1), SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_OUT(0, NULL, 1)), .offset = 0, .length = nor->mtd.size, }; struct spi_mem_op *op = &info.op_tmpl; /* get transfer protocols. */ op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); op->addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); op->dummy.buswidth = op->addr.buswidth; op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto); if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second) op->addr.nbytes = 0; nor->dirmap.wdesc = devm_spi_mem_dirmap_create(nor->dev, nor->spimem, &info); return PTR_ERR_OR_ZERO(nor->dirmap.wdesc); } static int spi_nor_probe(struct spi_mem *spimem) { struct spi_device *spi = spimem->spi; struct flash_platform_data *data = dev_get_platdata(&spi->dev); struct spi_nor *nor; /* * Enable all caps by default. The core will mask them after * checking what's really supported using spi_mem_supports_op(). */ const struct spi_nor_hwcaps hwcaps = { .mask = SNOR_HWCAPS_ALL }; char *flash_name; int ret; nor = devm_kzalloc(&spi->dev, sizeof(*nor), GFP_KERNEL); if (!nor) return -ENOMEM; nor->spimem = spimem; nor->dev = &spi->dev; spi_nor_set_flash_node(nor, spi->dev.of_node); spi_mem_set_drvdata(spimem, nor); if (data && data->name) nor->mtd.name = data->name; if (!nor->mtd.name) nor->mtd.name = spi_mem_get_name(spimem); /* * For some (historical?) reason many platforms provide two different * names in flash_platform_data: "name" and "type". Quite often name is * set to "m25p80" and then "type" provides a real chip name. * If that's the case, respect "type" and ignore a "name". */ if (data && data->type) flash_name = data->type; else if (!strcmp(spi->modalias, "spi-nor")) flash_name = NULL; /* auto-detect */ else flash_name = spi->modalias; ret = spi_nor_scan(nor, flash_name, &hwcaps); if (ret) return ret; /* * None of the existing parts have > 512B pages, but let's play safe * and add this logic so that if anyone ever adds support for such * a NOR we don't end up with buffer overflows. */ if (nor->page_size > PAGE_SIZE) { nor->bouncebuf_size = nor->page_size; devm_kfree(nor->dev, nor->bouncebuf); nor->bouncebuf = devm_kmalloc(nor->dev, nor->bouncebuf_size, GFP_KERNEL); if (!nor->bouncebuf) return -ENOMEM; } ret = spi_nor_create_read_dirmap(nor); if (ret) return ret; ret = spi_nor_create_write_dirmap(nor); if (ret) return ret; return mtd_device_register(&nor->mtd, data ? data->parts : NULL, data ? data->nr_parts : 0); } static int spi_nor_remove(struct spi_mem *spimem) { struct spi_nor *nor = spi_mem_get_drvdata(spimem); spi_nor_restore(nor); /* Clean up MTD stuff. */ return mtd_device_unregister(&nor->mtd); } static void spi_nor_shutdown(struct spi_mem *spimem) { struct spi_nor *nor = spi_mem_get_drvdata(spimem); spi_nor_restore(nor); } /* * Do NOT add to this array without reading the following: * * Historically, many flash devices are bound to this driver by their name. But * since most of these flash are compatible to some extent, and their * differences can often be differentiated by the JEDEC read-ID command, we * encourage new users to add support to the spi-nor library, and simply bind * against a generic string here (e.g., "jedec,spi-nor"). * * Many flash names are kept here in this list (as well as in spi-nor.c) to * keep them available as module aliases for existing platforms. */ static const struct spi_device_id spi_nor_dev_ids[] = { /* * Allow non-DT platform devices to bind to the "spi-nor" modalias, and * hack around the fact that the SPI core does not provide uevent * matching for .of_match_table */ {"spi-nor"}, /* * Entries not used in DTs that should be safe to drop after replacing * them with "spi-nor" in platform data. */ {"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"}, /* * Entries that were used in DTs without "jedec,spi-nor" fallback and * should be kept for backward compatibility. */ {"at25df321a"}, {"at25df641"}, {"at26df081a"}, {"mx25l4005a"}, {"mx25l1606e"}, {"mx25l6405d"}, {"mx25l12805d"}, {"mx25l25635e"},{"mx66l51235l"}, {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q512a"}, {"s25fl256s1"}, {"s25fl512s"}, {"s25sl12801"}, {"s25fl008k"}, {"s25fl064k"}, {"sst25vf040b"},{"sst25vf016b"},{"sst25vf032b"},{"sst25wf040"}, {"m25p40"}, {"m25p80"}, {"m25p16"}, {"m25p32"}, {"m25p64"}, {"m25p128"}, {"w25x80"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, {"w25q80bl"}, {"w25q128"}, {"w25q256"}, /* Flashes that can't be detected using JEDEC */ {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"}, {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"}, {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"}, /* Everspin MRAMs (non-JEDEC) */ { "mr25h128" }, /* 128 Kib, 40 MHz */ { "mr25h256" }, /* 256 Kib, 40 MHz */ { "mr25h10" }, /* 1 Mib, 40 MHz */ { "mr25h40" }, /* 4 Mib, 40 MHz */ { }, }; MODULE_DEVICE_TABLE(spi, spi_nor_dev_ids); static const struct of_device_id spi_nor_of_table[] = { /* * Generic compatibility for SPI NOR that can be identified by the * JEDEC READ ID opcode (0x9F). Use this, if possible. */ { .compatible = "jedec,spi-nor" }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, spi_nor_of_table); /* * REVISIT: many of these chips have deep power-down modes, which * should clearly be entered on suspend() to minimize power use. * And also when they're otherwise idle... */ static struct spi_mem_driver spi_nor_driver = { .spidrv = { .driver = { .name = "spi-nor", .of_match_table = spi_nor_of_table, }, .id_table = spi_nor_dev_ids, }, .probe = spi_nor_probe, .remove = spi_nor_remove, .shutdown = spi_nor_shutdown, }; module_spi_mem_driver(spi_nor_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Huang Shijie "); MODULE_AUTHOR("Mike Lavender"); MODULE_DESCRIPTION("framework for SPI NOR");