drivers/mtd/nand/raw/nuvoton-ma35d1-nand-controller.c

Source file repositories/reference/linux-study-clean/drivers/mtd/nand/raw/nuvoton-ma35d1-nand-controller.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/nuvoton-ma35d1-nand-controller.c
Extension
.c
Size
28102 bytes
Lines
1030
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 ma35_nand_chip {
	struct list_head node;
	struct nand_chip chip;

	u32 eccstatus;
	u8 nsels;
	u8 sels[] __counted_by(nsels);
};

struct ma35_nand_info {
	struct nand_controller controller;
	struct device *dev;
	void __iomem *regs;
	int irq;
	struct clk *clk;
	struct completion complete;
	struct list_head chips;

	u8 *buffer;
	unsigned long assigned_cs;
};

static inline struct ma35_nand_chip *to_ma35_nand(struct nand_chip *chip)
{
	return container_of(chip, struct ma35_nand_chip, chip);
}

static int ma35_ooblayout_ecc(struct mtd_info *mtd, int section,
			      struct mtd_oob_region *oob_region)
{
	struct nand_chip *chip = mtd_to_nand(mtd);

	if (section)
		return -ERANGE;

	oob_region->length = chip->ecc.total;
	oob_region->offset = mtd->oobsize - oob_region->length;

	return 0;
}

static int ma35_ooblayout_free(struct mtd_info *mtd, int section,
			       struct mtd_oob_region *oob_region)
{
	struct nand_chip *chip = mtd_to_nand(mtd);

	if (section)
		return -ERANGE;

	oob_region->length = mtd->oobsize - chip->ecc.total - 2;
	oob_region->offset = 2;

	return 0;
}

static const struct mtd_ooblayout_ops ma35_ooblayout_ops = {
	.free = ma35_ooblayout_free,
	.ecc = ma35_ooblayout_ecc,
};

static inline void ma35_clear_spare(struct nand_chip *chip, int size)
{
	struct ma35_nand_info *nand = nand_get_controller_data(chip);
	int i;

	for (i = 0; i < size / 4; i++)
		writel(0xff, nand->regs + MA35_NFI_REG_NANDRA0);
}

static inline void read_remaining_bytes(struct ma35_nand_info *nand, u32 *buf,
					u32 offset, int size, int swap)
{
	u32 value = readl(nand->regs + MA35_NFI_REG_NANDRA0 + offset);
	u8 *ptr = (u8 *)buf;
	int i, shift;

	for (i = 0; i < size; i++) {
		shift = (swap ? 3 - i : i) * 8;
		ptr[i] = (value >> shift) & 0xff;
	}
}

static inline void ma35_read_spare(struct nand_chip *chip, int size, u32 *buf, u32 offset)
{
	struct ma35_nand_info *nand = nand_get_controller_data(chip);
	u32 off = round_down(offset, 4);
	int len = offset % 4;
	int i;

	if (len) {

Annotation

Implementation Notes