drivers/spi/spi-mxic.c

Source file repositories/reference/linux-study-clean/drivers/spi/spi-mxic.c

File Facts

System
Linux kernel
Corpus path
drivers/spi/spi-mxic.c
Extension
.c
Size
21732 bytes
Lines
861
Domain
Driver Families
Bucket
drivers/spi
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_spi {
	struct device *dev;
	struct clk *ps_clk;
	struct clk *send_clk;
	struct clk *send_dly_clk;
	void __iomem *regs;
	u32 cur_speed_hz;
	struct {
		void __iomem *map;
		dma_addr_t dma;
		size_t size;
	} linear;

	struct {
		bool use_pipelined_conf;
		struct nand_ecc_engine *pipelined_engine;
		void *ctx;
	} ecc;
};

static int mxic_spi_clk_enable(struct mxic_spi *mxic)
{
	int ret;

	ret = clk_prepare_enable(mxic->send_clk);
	if (ret)
		return ret;

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

	return ret;

err_send_dly_clk:
	clk_disable_unprepare(mxic->send_clk);

	return ret;
}

static void mxic_spi_clk_disable(struct mxic_spi *mxic)
{
	clk_disable_unprepare(mxic->send_clk);
	clk_disable_unprepare(mxic->send_dly_clk);
}

static void mxic_spi_set_input_delay_dqs(struct mxic_spi *mxic, 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),
	       mxic->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),
	       mxic->regs + IDLY_CODE(1));
}

static int mxic_spi_clk_setup(struct mxic_spi *mxic, unsigned long freq)
{
	int ret;

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

	ret = clk_set_rate(mxic->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_spi_set_input_delay_dqs(mxic, 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(mxic->send_dly_clk, 9 * freq / 25000000);
	if (ret)
		return ret;

Annotation

Implementation Notes