drivers/mtd/spi-nor/micron-st.c

Source file repositories/reference/linux-study-clean/drivers/mtd/spi-nor/micron-st.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/spi-nor/micron-st.c
Extension
.c
Size
18421 bytes
Lines
673
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
			op.dummy.nbytes = nor->params->rdsr_dummy;
			/*
			 * We don't want to read only one byte in DTR mode. So,
			 * read 2 and then discard the second byte.
			 */
			op.data.nbytes = 2;
		}

		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);

		ret = spi_mem_exec_op(nor->spimem, &op);
	} else {
		ret = spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDFSR, fsr,
						      1);
	}

	if (ret)
		dev_dbg(nor->dev, "error %d reading FSR\n", ret);

	return ret;
}

/**
 * micron_st_nor_clear_fsr() - Clear the Flag Status Register.
 * @nor:	pointer to 'struct spi_nor'.
 */
static void micron_st_nor_clear_fsr(struct spi_nor *nor)
{
	int ret;

	if (nor->spimem) {
		struct spi_mem_op op = MICRON_ST_CLFSR_OP;

		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);

		ret = spi_mem_exec_op(nor->spimem, &op);
	} else {
		ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_CLFSR,
						       NULL, 0);
	}

	if (ret)
		dev_dbg(nor->dev, "error %d clearing FSR\n", ret);
}

/**
 * micron_st_nor_ready() - Query the Status Register as well as the Flag Status
 * Register to see if the flash is ready for new commands. If there are any
 * errors in the FSR clear them.
 * @nor:	pointer to 'struct spi_nor'.
 *
 * Return: 1 if ready, 0 if not ready, -errno on errors.
 */
static int micron_st_nor_ready(struct spi_nor *nor)
{
	int sr_ready, ret;

	sr_ready = spi_nor_sr_ready(nor);
	if (sr_ready < 0)
		return sr_ready;

	ret = micron_st_nor_read_fsr(nor, nor->bouncebuf);
	if (ret) {
		/*
		 * Some controllers, such as Intel SPI, do not support low
		 * level operations such as reading the flag status
		 * register. They only expose small amount of high level
		 * operations to the software. If this is the case we use
		 * only the status register value.
		 */
		return ret == -EOPNOTSUPP ? sr_ready : ret;
	}

	if (nor->bouncebuf[0] & (FSR_E_ERR | FSR_P_ERR)) {
		if (nor->bouncebuf[0] & FSR_E_ERR)
			dev_err(nor->dev, "Erase operation failed.\n");
		else
			dev_err(nor->dev, "Program operation failed.\n");

		if (nor->bouncebuf[0] & FSR_PT_ERR)
			dev_err(nor->dev,
				"Attempted to modify a protected sector.\n");

		micron_st_nor_clear_fsr(nor);

		/*
		 * WEL bit remains set to one when an erase or page program
		 * error occurs. Issue a Write Disable command to protect

Annotation

Implementation Notes