drivers/mtd/nand/raw/denali.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/raw/denali.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/denali.c
Extension
.c
Size
37647 bytes
Lines
1382
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

if (pos >= writesize) {
			pos += oob_skip;
		} else if (pos + len > writesize) {
			/* This chunk overwraps the BBM area. Must be split */
			ret = denali_change_column(chip, pos, buf,
						   writesize - pos, write);
			if (ret)
				return ret;

			buf += writesize - pos;
			len -= writesize - pos;
			pos = writesize + oob_skip;
		}

		ret = denali_change_column(chip, pos, buf, len, write);
		if (ret)
			return ret;

		buf += len;
	}

	return 0;
}

static int denali_oob_xfer(struct nand_chip *chip, void *buf, bool write)
{
	struct denali_controller *denali = to_denali_controller(chip);
	struct mtd_info *mtd = nand_to_mtd(chip);
	struct nand_ecc_ctrl *ecc = &chip->ecc;
	int writesize = mtd->writesize;
	int oobsize = mtd->oobsize;
	int oob_skip = denali->oob_skip_bytes;
	int ret, i, pos, len;

	/* BBM at the beginning of the OOB area */
	ret = denali_change_column(chip, writesize, buf, oob_skip, write);
	if (ret)
		return ret;

	buf += oob_skip;

	for (i = 0; i < ecc->steps; i++) {
		pos = ecc->size + i * (ecc->size + ecc->bytes);

		if (i == ecc->steps - 1)
			/* The last chunk includes OOB free */
			len = writesize + oobsize - pos - oob_skip;
		else
			len = ecc->bytes;

		if (pos >= writesize) {
			pos += oob_skip;
		} else if (pos + len > writesize) {
			/* This chunk overwraps the BBM area. Must be split */
			ret = denali_change_column(chip, pos, buf,
						   writesize - pos, write);
			if (ret)
				return ret;

			buf += writesize - pos;
			len -= writesize - pos;
			pos = writesize + oob_skip;
		}

		ret = denali_change_column(chip, pos, buf, len, write);
		if (ret)
			return ret;

		buf += len;
	}

	return 0;
}

static int denali_read_raw(struct nand_chip *chip, void *buf, void *oob_buf,
			   int page)
{
	int ret;

	if (!buf && !oob_buf)
		return -EINVAL;

	ret = nand_read_page_op(chip, page, 0, NULL, 0);
	if (ret)
		return ret;

	if (buf) {
		ret = denali_payload_xfer(chip, buf, false);
		if (ret)
			return ret;

Annotation

Implementation Notes