drivers/mtd/devices/mchp48l640.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mtd/devices/mchp48l640.c
Extension
.c
Size
9412 bytes
Lines
408
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 mchp48_caps {
	unsigned int size;
	unsigned int page_size;
	bool auto_disable_wel;
};

struct mchp48l640_flash {
	struct spi_device	*spi;
	struct mutex		lock;
	struct mtd_info		mtd;
	const struct mchp48_caps	*caps;
};

#define MCHP48L640_CMD_WREN		0x06
#define MCHP48L640_CMD_WRDI		0x04
#define MCHP48L640_CMD_WRITE		0x02
#define MCHP48L640_CMD_READ		0x03
#define MCHP48L640_CMD_WRSR		0x01
#define MCHP48L640_CMD_RDSR		0x05

#define MCHP48L640_STATUS_RDY		0x01
#define MCHP48L640_STATUS_WEL		0x02
#define MCHP48L640_STATUS_BP0		0x04
#define MCHP48L640_STATUS_BP1		0x08
#define MCHP48L640_STATUS_SWM		0x10
#define MCHP48L640_STATUS_PRO		0x20
#define MCHP48L640_STATUS_ASE		0x40

#define MCHP48L640_TIMEOUT		100

#define MAX_CMD_SIZE			0x10

#define to_mchp48l640_flash(x) container_of(x, struct mchp48l640_flash, mtd)

static int mchp48l640_mkcmd(struct mchp48l640_flash *flash, u8 cmd, loff_t addr, char *buf)
{
	buf[0] = cmd;
	buf[1] = addr >> 8;
	buf[2] = addr;

	return 3;
}

static int mchp48l640_read_status(struct mchp48l640_flash *flash, int *status)
{
	unsigned char cmd[2];
	int ret;

	cmd[0] = MCHP48L640_CMD_RDSR;
	cmd[1] = 0x00;
	mutex_lock(&flash->lock);
	ret = spi_write_then_read(flash->spi, &cmd[0], 1, &cmd[1], 1);
	mutex_unlock(&flash->lock);
	if (!ret)
		*status = cmd[1];
	dev_dbg(&flash->spi->dev, "read status ret: %d status: %x", ret, *status);

	return ret;
}

static int mchp48l640_waitforbit(struct mchp48l640_flash *flash, int bit, bool set)
{
	int ret, status;
	unsigned long deadline;

	deadline = jiffies + msecs_to_jiffies(MCHP48L640_TIMEOUT);
	do {
		ret = mchp48l640_read_status(flash, &status);
		dev_dbg(&flash->spi->dev, "read status ret: %d bit: %x %sset status: %x",
			ret, bit, (set ? "" : "not"), status);
		if (ret)
			return ret;

		if (set) {
			if ((status & bit) == bit)
				return 0;
		} else {
			if ((status & bit) == 0)
				return 0;
		}

		usleep_range(1000, 2000);
	} while (!time_after_eq(jiffies, deadline));

	dev_err(&flash->spi->dev, "Timeout waiting for bit %x %s set in status register.",
		bit, (set ? "" : "not"));
	return -ETIMEDOUT;
}

static int mchp48l640_write_prepare(struct mchp48l640_flash *flash, bool enable)

Annotation

Implementation Notes