drivers/mtd/spi-nor/controllers/nxp-spifi.c

Source file repositories/reference/linux-study-clean/drivers/mtd/spi-nor/controllers/nxp-spifi.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/spi-nor/controllers/nxp-spifi.c
Extension
.c
Size
11077 bytes
Lines
460
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 nxp_spifi {
	struct device *dev;
	struct clk *clk_spifi;
	struct clk *clk_reg;
	void __iomem *io_base;
	void __iomem *flash_base;
	struct spi_nor nor;
	bool memory_mode;
	u32 mcmd;
};

static int nxp_spifi_wait_for_cmd(struct nxp_spifi *spifi)
{
	u8 stat;
	int ret;

	ret = readb_poll_timeout(spifi->io_base + SPIFI_STAT, stat,
				 !(stat & SPIFI_STAT_CMD), 10, 30);
	if (ret)
		dev_warn(spifi->dev, "command timed out\n");

	return ret;
}

static int nxp_spifi_reset(struct nxp_spifi *spifi)
{
	u8 stat;
	int ret;

	writel(SPIFI_STAT_RESET, spifi->io_base + SPIFI_STAT);
	ret = readb_poll_timeout(spifi->io_base + SPIFI_STAT, stat,
				 !(stat & SPIFI_STAT_RESET), 10, 30);
	if (ret)
		dev_warn(spifi->dev, "state reset timed out\n");

	return ret;
}

static int nxp_spifi_set_memory_mode_off(struct nxp_spifi *spifi)
{
	int ret;

	if (!spifi->memory_mode)
		return 0;

	ret = nxp_spifi_reset(spifi);
	if (ret)
		dev_err(spifi->dev, "unable to enter command mode\n");
	else
		spifi->memory_mode = false;

	return ret;
}

static int nxp_spifi_set_memory_mode_on(struct nxp_spifi *spifi)
{
	u8 stat;
	int ret;

	if (spifi->memory_mode)
		return 0;

	writel(spifi->mcmd, spifi->io_base + SPIFI_MCMD);
	ret = readb_poll_timeout(spifi->io_base + SPIFI_STAT, stat,
				 stat & SPIFI_STAT_MCINIT, 10, 30);
	if (ret)
		dev_err(spifi->dev, "unable to enter memory mode\n");
	else
		spifi->memory_mode = true;

	return ret;
}

static int nxp_spifi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
			      size_t len)
{
	struct nxp_spifi *spifi = nor->priv;
	u32 cmd;
	int ret;

	ret = nxp_spifi_set_memory_mode_off(spifi);
	if (ret)
		return ret;

	cmd = SPIFI_CMD_DATALEN(len) |
	      SPIFI_CMD_OPCODE(opcode) |
	      SPIFI_CMD_FIELDFORM_ALL_SERIAL |
	      SPIFI_CMD_FRAMEFORM_OPCODE_ONLY;
	writel(cmd, spifi->io_base + SPIFI_CMD);

Annotation

Implementation Notes