linux/drivers/mtd/devices/mtd_dataflash.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework
 *
 * Largely derived from at91_dataflash.c:
 *  Copyright (C) 2003-2005 SAN People (Pty) Ltd
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/math64.h>
#include <linux/of.h>

#include <linux/spi/spi.h>
#include <linux/spi/flash.h>

#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>

/*
 * DataFlash is a kind of SPI flash.  Most AT45 chips have two buffers in
 * each chip, which may be used for double buffered I/O; but this driver
 * doesn't (yet) use these for any kind of i/o overlap or prefetching.
 *
 * Sometimes DataFlash is packaged in MMC-format cards, although the
 * MMC stack can't (yet?) distinguish between MMC and DataFlash
 * protocols during enumeration.
 */

/* reads can bypass the buffers */
#define OP_READ_CONTINUOUS
#define OP_READ_PAGE

/* group B requests can run even while status reports "busy" */
#define OP_READ_STATUS

/* move data between host and buffer */
#define OP_READ_BUFFER1
#define OP_READ_BUFFER2
#define OP_WRITE_BUFFER1
#define OP_WRITE_BUFFER2

/* erasing flash */
#define OP_ERASE_PAGE
#define OP_ERASE_BLOCK

/* move data between buffer and flash */
#define OP_TRANSFER_BUF1
#define OP_TRANSFER_BUF2
#define OP_MREAD_BUFFER1
#define OP_MREAD_BUFFER2
#define OP_MWERASE_BUFFER1
#define OP_MWERASE_BUFFER2
#define OP_MWRITE_BUFFER1
#define OP_MWRITE_BUFFER2

/* write to buffer, then write-erase to flash */
#define OP_PROGRAM_VIA_BUF1
#define OP_PROGRAM_VIA_BUF2

/* compare buffer to flash */
#define OP_COMPARE_BUF1
#define OP_COMPARE_BUF2

/* read flash to buffer, then write-erase to flash */
#define OP_REWRITE_VIA_BUF1
#define OP_REWRITE_VIA_BUF2

/* newer chips report JEDEC manufacturer and device IDs; chip
 * serial number and OTP bits; and per-sector writeprotect.
 */
#define OP_READ_ID
#define OP_READ_SECURITY
#define OP_WRITE_SECURITY_REVC
#define OP_WRITE_SECURITY

#define CFI_MFR_ATMEL

#define DATAFLASH_SHIFT_EXTID
#define DATAFLASH_SHIFT_ID

struct dataflash {};

#ifdef CONFIG_OF
static const struct of_device_id dataflash_dt_ids[] =;
MODULE_DEVICE_TABLE(of, dataflash_dt_ids);
#endif

static const struct spi_device_id dataflash_spi_ids[] =;
MODULE_DEVICE_TABLE(spi, dataflash_spi_ids);

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

/*
 * Return the status of the DataFlash device.
 */
static inline int dataflash_status(struct spi_device *spi)
{}

/*
 * 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)
{}

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

/*
 * Erase pages of flash.
 */
static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
{}

/*
 * Read from the DataFlash device.
 *   from   : Start offset in flash device
 *   len    : Amount to read
 *   retlen : About of data actually read
 *   buf    : Buffer containing the data
 */
static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
			       size_t *retlen, u_char *buf)
{}

/*
 * Write to the DataFlash device.
 *   to     : Start offset in flash device
 *   len    : Amount to write
 *   retlen : Amount of data actually written
 *   buf    : Buffer containing the data
 */
static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
				size_t * retlen, const u_char * buf)
{}

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

#ifdef CONFIG_MTD_DATAFLASH_OTP

static int dataflash_get_otp_info(struct mtd_info *mtd, size_t len,
				  size_t *retlen, struct otp_info *info)
{}

static ssize_t otp_read(struct spi_device *spi, unsigned base,
		u8 *buf, loff_t off, size_t len)
{}

static int dataflash_read_fact_otp(struct mtd_info *mtd,
		loff_t from, size_t len, size_t *retlen, u_char *buf)
{}

static int dataflash_read_user_otp(struct mtd_info *mtd,
		loff_t from, size_t len, size_t *retlen, u_char *buf)
{}

static int dataflash_write_user_otp(struct mtd_info *mtd,
		loff_t from, size_t len, size_t *retlen, const u_char *buf)
{}

static char *otp_setup(struct mtd_info *device, char revision)
{}

#else

static char *otp_setup(struct mtd_info *device, char revision)
{
	return " (OTP)";
}

#endif

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

/*
 * Register DataFlash device with MTD subsystem.
 */
static int add_dataflash_otp(struct spi_device *spi, char *name, int nr_pages,
			     int pagesize, int pageoffset, char revision)
{}

static inline int add_dataflash(struct spi_device *spi, char *name,
				int nr_pages, int pagesize, int pageoffset)
{}

struct flash_info {};

static struct flash_info dataflash_data[] =;

static struct flash_info *jedec_lookup(struct spi_device *spi,
				       u64 jedec, bool use_extid)
{}

static struct flash_info *jedec_probe(struct spi_device *spi)
{}

/*
 * Detect and initialize DataFlash device, using JEDEC IDs on newer chips
 * or else the ID code embedded in the status bits:
 *
 *   Device      Density         ID code          #Pages PageSize  Offset
 *   AT45DB011B  1Mbit   (128K)  xx0011xx (0x0c)    512    264      9
 *   AT45DB021B  2Mbit   (256K)  xx0101xx (0x14)   1024    264      9
 *   AT45DB041B  4Mbit   (512K)  xx0111xx (0x1c)   2048    264      9
 *   AT45DB081B  8Mbit   (1M)    xx1001xx (0x24)   4096    264      9
 *   AT45DB0161B 16Mbit  (2M)    xx1011xx (0x2c)   4096    528     10
 *   AT45DB0321B 32Mbit  (4M)    xx1101xx (0x34)   8192    528     10
 *   AT45DB0642  64Mbit  (8M)    xx111xxx (0x3c)   8192   1056     11
 *   AT45DB1282  128Mbit (16M)   xx0100xx (0x10)  16384   1056     11
 */
static int dataflash_probe(struct spi_device *spi)
{}

static void dataflash_remove(struct spi_device *spi)
{}

static struct spi_driver dataflash_driver =;

module_spi_driver();

MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_ALIAS();