drivers/mtd/nand/raw/technologic-nand-controller.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/technologic-nand-controller.c
Extension
.c
Size
5686 bytes
Lines
223
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 ts72xx_nand_data {
	struct nand_controller	controller;
	struct nand_chip	chip;
	void __iomem		*base;
	void __iomem		*ctrl;
	void __iomem		*busy;
};

static inline struct ts72xx_nand_data *chip_to_ts72xx(struct nand_chip *chip)
{
	return container_of(chip, struct ts72xx_nand_data, chip);
}

static int ts72xx_nand_attach_chip(struct nand_chip *chip)
{
	switch (chip->ecc.engine_type) {
	case NAND_ECC_ENGINE_TYPE_ON_HOST:
		return -EINVAL;
	case NAND_ECC_ENGINE_TYPE_SOFT:
		if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN)
			chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
		chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
		fallthrough;
	default:
		return 0;
	}
}

static void ts72xx_nand_ctrl(struct nand_chip *chip, u8 value)
{
	struct ts72xx_nand_data *data = chip_to_ts72xx(chip);
	unsigned char bits = ioread8(data->ctrl) & ~GENMASK(2, 0);

	iowrite8(bits | value, data->ctrl);
}

static int ts72xx_nand_exec_instr(struct nand_chip *chip,
				const struct nand_op_instr *instr)
{
	struct ts72xx_nand_data *data = chip_to_ts72xx(chip);
	unsigned int timeout_us;
	u32 status;
	int ret;

	switch (instr->type) {
	case NAND_OP_CMD_INSTR:
		ts72xx_nand_ctrl(chip, TS72XX_NAND_CTRL_CLE);
		iowrite8(instr->ctx.cmd.opcode, data->base);
		ts72xx_nand_ctrl(chip, TS72XX_NAND_NCE);
		break;

	case NAND_OP_ADDR_INSTR:
		ts72xx_nand_ctrl(chip, TS72XX_NAND_CTRL_ALE);
		iowrite8_rep(data->base, instr->ctx.addr.addrs, instr->ctx.addr.naddrs);
		ts72xx_nand_ctrl(chip, TS72XX_NAND_NCE);
		break;

	case NAND_OP_DATA_IN_INSTR:
		ioread8_rep(data->base, instr->ctx.data.buf.in, instr->ctx.data.len);
		break;

	case NAND_OP_DATA_OUT_INSTR:
		iowrite8_rep(data->base, instr->ctx.data.buf.in, instr->ctx.data.len);
		break;

	case NAND_OP_WAITRDY_INSTR:
		timeout_us = instr->ctx.waitrdy.timeout_ms * 1000;
		ret = readb_poll_timeout(data->busy, status, status & BIT(5), 0, timeout_us);
		if (ret)
			return ret;

		break;
	}

	if (instr->delay_ns)
		ndelay(instr->delay_ns);

	return 0;
}

static int ts72xx_nand_exec_op(struct nand_chip *chip,
			       const struct nand_operation *op, bool check_only)
{
	unsigned int i;
	int ret;

	if (check_only)
		return 0;

	for (i = 0; i < op->ninstrs; i++) {

Annotation

Implementation Notes