drivers/mtd/nand/raw/mxic_nand.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mtd/nand/raw/mxic_nand.c
Extension
.c
Size
14106 bytes
Lines
588
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 mxic_nand_ctlr {
	struct clk *ps_clk;
	struct clk *send_clk;
	struct clk *send_dly_clk;
	struct completion complete;
	void __iomem *regs;
	struct nand_controller controller;
	struct device *dev;
	struct nand_chip chip;
};

static int mxic_nfc_clk_enable(struct mxic_nand_ctlr *nfc)
{
	int ret;

	ret = clk_prepare_enable(nfc->ps_clk);
	if (ret)
		return ret;

	ret = clk_prepare_enable(nfc->send_clk);
	if (ret)
		goto err_ps_clk;

	ret = clk_prepare_enable(nfc->send_dly_clk);
	if (ret)
		goto err_send_dly_clk;

	return ret;

err_send_dly_clk:
	clk_disable_unprepare(nfc->send_clk);
err_ps_clk:
	clk_disable_unprepare(nfc->ps_clk);

	return ret;
}

static void mxic_nfc_clk_disable(struct mxic_nand_ctlr *nfc)
{
	clk_disable_unprepare(nfc->send_clk);
	clk_disable_unprepare(nfc->send_dly_clk);
	clk_disable_unprepare(nfc->ps_clk);
}

static void mxic_nfc_set_input_delay(struct mxic_nand_ctlr *nfc, u8 idly_code)
{
	writel(IDLY_CODE_VAL(0, idly_code) |
	       IDLY_CODE_VAL(1, idly_code) |
	       IDLY_CODE_VAL(2, idly_code) |
	       IDLY_CODE_VAL(3, idly_code),
	       nfc->regs + IDLY_CODE(0));
	writel(IDLY_CODE_VAL(4, idly_code) |
	       IDLY_CODE_VAL(5, idly_code) |
	       IDLY_CODE_VAL(6, idly_code) |
	       IDLY_CODE_VAL(7, idly_code),
	       nfc->regs + IDLY_CODE(1));
}

static int mxic_nfc_clk_setup(struct mxic_nand_ctlr *nfc, unsigned long freq)
{
	int ret;

	ret = clk_set_rate(nfc->send_clk, freq);
	if (ret)
		return ret;

	ret = clk_set_rate(nfc->send_dly_clk, freq);
	if (ret)
		return ret;

	/*
	 * A constant delay range from 0x0 ~ 0x1F for input delay,
	 * the unit is 78 ps, the max input delay is 2.418 ns.
	 */
	mxic_nfc_set_input_delay(nfc, 0xf);

	/*
	 * Phase degree = 360 * freq * output-delay
	 * where output-delay is a constant value 1 ns in FPGA.
	 *
	 * Get Phase degree = 360 * freq * 1 ns
	 *                  = 360 * freq * 1 sec / 1000000000
	 *                  = 9 * freq / 25000000
	 */
	ret = clk_set_phase(nfc->send_dly_clk, 9 * freq / 25000000);
	if (ret)
		return ret;

	return 0;
}

Annotation

Implementation Notes