drivers/mtd/devices/mchp23k256.c

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

File Facts

System
Linux kernel
Corpus path
drivers/mtd/devices/mchp23k256.c
Extension
.c
Size
5878 bytes
Lines
260
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 mchp23_caps {
	u8 addr_width;
	unsigned int size;
};

struct mchp23k256_flash {
	struct spi_device	*spi;
	struct mutex		lock;
	struct mtd_info		mtd;
	const struct mchp23_caps	*caps;
};

#define MCHP23K256_CMD_WRITE_STATUS	0x01
#define MCHP23K256_CMD_WRITE		0x02
#define MCHP23K256_CMD_READ		0x03
#define MCHP23K256_MODE_SEQ		BIT(6)

#define to_mchp23k256_flash(x) container_of(x, struct mchp23k256_flash, mtd)

static void mchp23k256_addr2cmd(struct mchp23k256_flash *flash,
				unsigned int addr, u8 *cmd)
{
	int i;

	/*
	 * Address is sent in big endian (MSB first) and we skip
	 * the first entry of the cmd array which contains the cmd
	 * opcode.
	 */
	for (i = flash->caps->addr_width; i > 0; i--, addr >>= 8)
		cmd[i] = addr;
}

static int mchp23k256_cmdsz(struct mchp23k256_flash *flash)
{
	return 1 + flash->caps->addr_width;
}

static int mchp23k256_write(struct mtd_info *mtd, loff_t to, size_t len,
			    size_t *retlen, const unsigned char *buf)
{
	struct mchp23k256_flash *flash = to_mchp23k256_flash(mtd);
	struct spi_transfer transfer[2] = {};
	struct spi_message message;
	unsigned char command[MAX_CMD_SIZE];
	int ret, cmd_len;

	spi_message_init(&message);

	cmd_len = mchp23k256_cmdsz(flash);

	command[0] = MCHP23K256_CMD_WRITE;
	mchp23k256_addr2cmd(flash, to, command);

	transfer[0].tx_buf = command;
	transfer[0].len = cmd_len;
	spi_message_add_tail(&transfer[0], &message);

	transfer[1].tx_buf = buf;
	transfer[1].len = len;
	spi_message_add_tail(&transfer[1], &message);

	mutex_lock(&flash->lock);

	ret = spi_sync(flash->spi, &message);

	mutex_unlock(&flash->lock);

	if (ret)
		return ret;

	if (retlen && message.actual_length > cmd_len)
		*retlen += message.actual_length - cmd_len;

	return 0;
}

static int mchp23k256_read(struct mtd_info *mtd, loff_t from, size_t len,
			   size_t *retlen, unsigned char *buf)
{
	struct mchp23k256_flash *flash = to_mchp23k256_flash(mtd);
	struct spi_transfer transfer[2] = {};
	struct spi_message message;
	unsigned char command[MAX_CMD_SIZE];
	int ret, cmd_len;

	spi_message_init(&message);

	cmd_len = mchp23k256_cmdsz(flash);

Annotation

Implementation Notes