drivers/mtd/devices/mtd_dataflash.c

Source file repositories/reference/linux-study-clean/drivers/mtd/devices/mtd_dataflash.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/devices/mtd_dataflash.c
Extension
.c
Size
24891 bytes
Lines
947
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 dataflash {
	u8			command[4];
	char			name[24];

	unsigned short		page_offset;	/* offset in flash address */
	unsigned int		page_size;	/* of bytes per page */

	struct mutex		lock;
	struct spi_device	*spi;

	struct mtd_info		mtd;
};

#ifdef CONFIG_OF
static const struct of_device_id dataflash_dt_ids[] = {
	{ .compatible = "atmel,at45", },
	{ .compatible = "atmel,dataflash", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, dataflash_dt_ids);
#endif

static const struct spi_device_id dataflash_spi_ids[] = {
	{ .name = "at45", },
	{ .name = "dataflash", },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(spi, dataflash_spi_ids);

/* ......................................................................... */

/*
 * Return the status of the DataFlash device.
 */
static inline int dataflash_status(struct spi_device *spi)
{
	/* NOTE:  at45db321c over 25 MHz wants to write
	 * a dummy byte after the opcode...
	 */
	return spi_w8r8(spi, OP_READ_STATUS);
}

/*
 * Poll the DataFlash device until it is READY.
 * This usually takes 5-20 msec or so; more for sector erase.
 */
static int dataflash_waitready(struct spi_device *spi)
{
	int	status;

	for (;;) {
		status = dataflash_status(spi);
		if (status < 0) {
			dev_dbg(&spi->dev, "status %d?\n", status);
			status = 0;
		}

		if (status & (1 << 7))	/* RDY/nBSY */
			return status;

		usleep_range(3000, 4000);
	}
}

/* ......................................................................... */

/*
 * Erase pages of flash.
 */
static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
{
	struct dataflash	*priv = mtd->priv;
	struct spi_device	*spi = priv->spi;
	struct spi_transfer	x = { };
	struct spi_message	msg;
	unsigned		blocksize = priv->page_size << 3;
	u8			*command;
	u32			rem;

	dev_dbg(&spi->dev, "erase addr=0x%llx len 0x%llx\n",
		(long long)instr->addr, (long long)instr->len);

	div_u64_rem(instr->len, priv->page_size, &rem);
	if (rem)
		return -EINVAL;
	div_u64_rem(instr->addr, priv->page_size, &rem);
	if (rem)
		return -EINVAL;

	spi_message_init(&msg);

Annotation

Implementation Notes