drivers/mtd/nand/ecc-mxic.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/ecc-mxic.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/ecc-mxic.c
Extension
.c
Size
23365 bytes
Lines
879
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 mxic_ecc_engine {
	struct device *dev;
	void __iomem *regs;
	int irq;
	struct completion complete;
	struct nand_ecc_engine external_engine;
	struct nand_ecc_engine pipelined_engine;
	struct mutex lock;
};

struct mxic_ecc_ctx {
	/* ECC machinery */
	unsigned int data_step_sz;
	unsigned int oob_step_sz;
	unsigned int parity_sz;
	unsigned int meta_sz;
	u8 *status;
	int steps;

	/* DMA boilerplate */
	struct nand_ecc_req_tweak_ctx req_ctx;
	u8 *oobwithstat;
	struct scatterlist sg[2];
	struct nand_page_io_req *req;
	unsigned int pageoffs;
};

static struct mxic_ecc_engine *ext_ecc_eng_to_mxic(struct nand_ecc_engine *eng)
{
	return container_of(eng, struct mxic_ecc_engine, external_engine);
}

static struct mxic_ecc_engine *pip_ecc_eng_to_mxic(struct nand_ecc_engine *eng)
{
	return container_of(eng, struct mxic_ecc_engine, pipelined_engine);
}

static struct mxic_ecc_engine *nand_to_mxic(struct nand_device *nand)
{
	struct nand_ecc_engine *eng = nand->ecc.engine;

	if (eng->integration == NAND_ECC_ENGINE_INTEGRATION_EXTERNAL)
		return ext_ecc_eng_to_mxic(eng);
	else
		return pip_ecc_eng_to_mxic(eng);
}

static int mxic_ecc_ooblayout_ecc(struct mtd_info *mtd, int section,
				  struct mtd_oob_region *oobregion)
{
	struct nand_device *nand = mtd_to_nanddev(mtd);
	struct mxic_ecc_ctx *ctx = nand_to_ecc_ctx(nand);

	if (section < 0 || section >= ctx->steps)
		return -ERANGE;

	oobregion->offset = (section * ctx->oob_step_sz) + ctx->meta_sz;
	oobregion->length = ctx->parity_sz;

	return 0;
}

static int mxic_ecc_ooblayout_free(struct mtd_info *mtd, int section,
				   struct mtd_oob_region *oobregion)
{
	struct nand_device *nand = mtd_to_nanddev(mtd);
	struct mxic_ecc_ctx *ctx = nand_to_ecc_ctx(nand);

	if (section < 0 || section >= ctx->steps)
		return -ERANGE;

	if (!section) {
		oobregion->offset = 2;
		oobregion->length = ctx->meta_sz - 2;
	} else {
		oobregion->offset = section * ctx->oob_step_sz;
		oobregion->length = ctx->meta_sz;
	}

	return 0;
}

static const struct mtd_ooblayout_ops mxic_ecc_ooblayout_ops = {
	.ecc = mxic_ecc_ooblayout_ecc,
	.free = mxic_ecc_ooblayout_free,
};

static void mxic_ecc_disable_engine(struct mxic_ecc_engine *mxic)
{
	u32 reg;

Annotation

Implementation Notes