drivers/mtd/nand/spi/macronix.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/spi/macronix.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/spi/macronix.c
Extension
.c
Size
19923 bytes
Lines
546
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

struct macronix_priv {
	bool cont_read;
};

static SPINAND_OP_VARIANTS(read_cache_variants,
		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0, 0),
		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0, 0),
		SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0, 0),
		SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0, 0));

static SPINAND_OP_VARIANTS(write_cache_variants,
		SPINAND_PROG_LOAD_1S_1S_4S_OP(true, 0, NULL, 0),
		SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0));

static SPINAND_OP_VARIANTS(update_cache_variants,
		SPINAND_PROG_LOAD_1S_1S_4S_OP(false, 0, NULL, 0),
		SPINAND_PROG_LOAD_1S_1S_1S_OP(false, 0, NULL, 0));

#define SPINAND_MACRONIX_READ_ECCSR_1S_0_1S(buf)			\
	SPI_MEM_OP(SPI_MEM_OP_CMD(0x7c, 1),				\
		   SPI_MEM_OP_NO_ADDR,					\
		   SPI_MEM_OP_DUMMY(1, 1),				\
		   SPI_MEM_OP_DATA_IN(1, buf, 1))

static SPINAND_OP_VARIANTS(macronix_ops,
		SPINAND_MACRONIX_READ_ECCSR_1S_0_1S(NULL));

static struct spi_mem_op
spinand_fill_macronix_read_eccsr_op(struct spinand_device *spinand, void *valptr)
{
	WARN_ON_ONCE(spinand->bus_iface != SSDR);

	return (struct spi_mem_op)SPINAND_MACRONIX_READ_ECCSR_1S_0_1S(valptr);
}

static int mx35lfxge4ab_ooblayout_ecc(struct mtd_info *mtd, int section,
				      struct mtd_oob_region *region)
{
	return -ERANGE;
}

static int mx35lfxge4ab_ooblayout_free(struct mtd_info *mtd, int section,
				       struct mtd_oob_region *region)
{
	if (section)
		return -ERANGE;

	region->offset = 2;
	region->length = mtd->oobsize - 2;

	return 0;
}

static const struct mtd_ooblayout_ops mx35lfxge4ab_ooblayout = {
	.ecc = mx35lfxge4ab_ooblayout_ecc,
	.free = mx35lfxge4ab_ooblayout_free,
};

static int macronix_get_eccsr(struct spinand_device *spinand, u8 *eccsr)
{
	struct macronix_priv *priv = spinand->priv;
	struct spi_mem_op op = SPINAND_OP(spinand, macronix_read_eccsr, eccsr);
	int ret;

	ret = spi_mem_exec_op(spinand->spimem, &op);
	if (ret)
		return ret;

	/*
	 * ECCSR exposes the number of bitflips for the last read page in bits [3:0].
	 * Continuous read compatible chips also expose the maximum number of
	 * bitflips for the whole (continuous) read operation in bits [7:4].
	 */
	if (!priv->cont_read)
		*eccsr = MACRONIX_ECCSR_BF_LAST_PAGE(*eccsr);
	else
		*eccsr = MACRONIX_ECCSR_BF_ACCUMULATED_PAGES(*eccsr);

	return 0;
}

static int macronix_ecc_get_status(struct spinand_device *spinand,
				   u8 status)
{
	struct nand_device *nand = spinand_to_nand(spinand);
	u8 eccsr;

	switch (status & STATUS_ECC_MASK) {
	case STATUS_ECC_NO_BITFLIPS:
		return 0;

Annotation

Implementation Notes