drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
Extension
.c
Size
14216 bytes
Lines
562
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 jz_soc_info {
	unsigned long data_offset;
	unsigned long addr_offset;
	unsigned long cmd_offset;
	const struct mtd_ooblayout_ops *oob_layout;
	bool oob_first;
};

struct ingenic_nand_cs {
	unsigned int bank;
	void __iomem *base;
};

struct ingenic_nfc {
	struct device *dev;
	struct ingenic_ecc *ecc;
	const struct jz_soc_info *soc_info;
	struct nand_controller controller;
	unsigned int num_banks;
	struct list_head chips;
	struct ingenic_nand_cs cs[] __counted_by(num_banks);
};

struct ingenic_nand {
	struct nand_chip chip;
	struct list_head chip_list;

	struct gpio_desc *busy_gpio;
	struct gpio_desc *wp_gpio;
	unsigned int reading: 1;
};

static inline struct ingenic_nand *to_ingenic_nand(struct mtd_info *mtd)
{
	return container_of(mtd_to_nand(mtd), struct ingenic_nand, chip);
}

static inline struct ingenic_nfc *to_ingenic_nfc(struct nand_controller *ctrl)
{
	return container_of(ctrl, struct ingenic_nfc, controller);
}

static int qi_lb60_ooblayout_ecc(struct mtd_info *mtd, int section,
				 struct mtd_oob_region *oobregion)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct nand_ecc_ctrl *ecc = &chip->ecc;

	if (section || !ecc->total)
		return -ERANGE;

	oobregion->length = ecc->total;
	oobregion->offset = 12;

	return 0;
}

static int qi_lb60_ooblayout_free(struct mtd_info *mtd, int section,
				  struct mtd_oob_region *oobregion)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct nand_ecc_ctrl *ecc = &chip->ecc;

	if (section)
		return -ERANGE;

	oobregion->length = mtd->oobsize - ecc->total - 12;
	oobregion->offset = 12 + ecc->total;

	return 0;
}

static const struct mtd_ooblayout_ops qi_lb60_ooblayout_ops = {
	.ecc = qi_lb60_ooblayout_ecc,
	.free = qi_lb60_ooblayout_free,
};

static int jz4725b_ooblayout_ecc(struct mtd_info *mtd, int section,
				 struct mtd_oob_region *oobregion)
{
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct nand_ecc_ctrl *ecc = &chip->ecc;

	if (section || !ecc->total)
		return -ERANGE;

	oobregion->length = ecc->total;
	oobregion->offset = 3;

	return 0;

Annotation

Implementation Notes