spi-nor.h 7.3 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * Copyright (C) 2014 Freescale Semiconductor, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

10 11 12 13
#ifndef __LINUX_MTD_SPI_NOR_H
#define __LINUX_MTD_SPI_NOR_H

/* Flash opcodes. */
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
#define SPINOR_OP_WREN		0x06	/* Write enable */
#define SPINOR_OP_RDSR		0x05	/* Read status register */
#define SPINOR_OP_WRSR		0x01	/* Write status register 1 byte */
#define SPINOR_OP_NORM_READ	0x03	/* Read data bytes (low frequency) */
#define SPINOR_OP_FAST_READ	0x0b	/* Read data bytes (high frequency) */
#define SPINOR_OP_DUAL_READ	0x3b	/* Read data bytes (Dual SPI) */
#define SPINOR_OP_QUAD_READ	0x6b	/* Read data bytes (Quad SPI) */
#define SPINOR_OP_PP		0x02	/* Page program (up to 256 bytes) */
#define SPINOR_OP_BE_4K		0x20	/* Erase 4KiB block */
#define SPINOR_OP_BE_4K_PMC	0xd7	/* Erase 4KiB block on PMC chips */
#define SPINOR_OP_BE_32K	0x52	/* Erase 32KiB block */
#define SPINOR_OP_CHIP_ERASE	0xc7	/* Erase whole flash chip */
#define SPINOR_OP_SE		0xd8	/* Sector erase (usually 64KiB) */
#define SPINOR_OP_RDID		0x9f	/* Read JEDEC ID */
#define SPINOR_OP_RDCR		0x35	/* Read configuration register */
29 30

/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
31 32 33 34 35 36
#define SPINOR_OP_NORM_READ_4B	0x13	/* Read data bytes (low frequency) */
#define SPINOR_OP_FAST_READ_4B	0x0c	/* Read data bytes (high frequency) */
#define SPINOR_OP_DUAL_READ_4B	0x3c	/* Read data bytes (Dual SPI) */
#define SPINOR_OP_QUAD_READ_4B	0x6c	/* Read data bytes (Quad SPI) */
#define SPINOR_OP_PP_4B		0x12	/* Page program (up to 256 bytes) */
#define SPINOR_OP_SE_4B		0xdc	/* Sector erase (usually 64KiB) */
37 38

/* Used for SST flashes only. */
39 40 41
#define SPINOR_OP_BP		0x02	/* Byte program */
#define SPINOR_OP_WRDI		0x04	/* Write disable */
#define SPINOR_OP_AAI_WP	0xad	/* Auto address increment word program */
42 43

/* Used for Macronix and Winbond flashes. */
44 45
#define SPINOR_OP_EN4B		0xb7	/* Enter 4-byte mode */
#define SPINOR_OP_EX4B		0xe9	/* Exit 4-byte mode */
46 47

/* Used for Spansion flashes only. */
48
#define SPINOR_OP_BRWR		0x17	/* Bank register write */
49 50

/* Status Register bits. */
51 52
#define SR_WIP			1	/* Write in progress */
#define SR_WEL			2	/* Write enable latch */
53
/* meaning of other SR_* bits may differ between vendors */
54 55 56 57
#define SR_BP0			4	/* Block protect 0 */
#define SR_BP1			8	/* Block protect 1 */
#define SR_BP2			0x10	/* Block protect 2 */
#define SR_SRWD			0x80	/* SR write protect */
58

59
#define SR_QUAD_EN_MX		0x40	/* Macronix Quad I/O */
60 61

/* Configuration Register bits. */
62
#define CR_QUAD_EN_SPAN		0x2	/* Spansion Quad I/O */
63

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
enum read_mode {
	SPI_NOR_NORMAL = 0,
	SPI_NOR_FAST,
	SPI_NOR_DUAL,
	SPI_NOR_QUAD,
};

/**
 * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
 * @wren:		command for "Write Enable", or 0x00 for not required
 * @cmd:		command for operation
 * @cmd_pins:		number of pins to send @cmd (1, 2, 4)
 * @addr:		address for operation
 * @addr_pins:		number of pins to send @addr (1, 2, 4)
 * @addr_width:		number of address bytes
 *			(3,4, or 0 for address not required)
 * @mode:		mode data
 * @mode_pins:		number of pins to send @mode (1, 2, 4)
 * @mode_cycles:	number of mode cycles (0 for mode not required)
 * @dummy_cycles:	number of dummy cycles (0 for dummy not required)
 */
struct spi_nor_xfer_cfg {
	u8		wren;
	u8		cmd;
	u8		cmd_pins;
	u32		addr;
	u8		addr_pins;
	u8		addr_width;
	u8		mode;
	u8		mode_pins;
	u8		mode_cycles;
	u8		dummy_cycles;
};

98
#define SPI_NOR_MAX_CMD_SIZE	8
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
enum spi_nor_ops {
	SPI_NOR_OPS_READ = 0,
	SPI_NOR_OPS_WRITE,
	SPI_NOR_OPS_ERASE,
	SPI_NOR_OPS_LOCK,
	SPI_NOR_OPS_UNLOCK,
};

/**
 * struct spi_nor - Structure for defining a the SPI NOR layer
 * @mtd:		point to a mtd_info structure
 * @lock:		the lock for the read/write/erase/lock/unlock operations
 * @dev:		point to a spi device, or a spi nor controller device.
 * @page_size:		the page size of the SPI NOR
 * @addr_width:		number of address bytes
 * @erase_opcode:	the opcode for erasing a sector
 * @read_opcode:	the read opcode
 * @read_dummy:		the dummy needed by the read operation
 * @program_opcode:	the program opcode
 * @flash_read:		the mode of the read
 * @sst_write_second:	used by the SST write operation
 * @cfg:		used by the read_xfer/write_xfer
 * @cmd_buf:		used by the write_reg
 * @prepare:		[OPTIONAL] do some preparations for the
 *			read/write/erase/lock/unlock operations
 * @unprepare:		[OPTIONAL] do some post work after the
 *			read/write/erase/lock/unlock operations
 * @read_xfer:		[OPTIONAL] the read fundamental primitive
 * @write_xfer:		[OPTIONAL] the writefundamental primitive
 * @read_reg:		[DRIVER-SPECIFIC] read out the register
 * @write_reg:		[DRIVER-SPECIFIC] write data to the register
 * @read_id:		[REPLACEABLE] read out the ID data, and find
 *			the proper spi_device_id
 * @wait_till_ready:	[REPLACEABLE] wait till the NOR becomes ready
 * @read:		[DRIVER-SPECIFIC] read data from the SPI NOR
 * @write:		[DRIVER-SPECIFIC] write data to the SPI NOR
 * @erase:		[DRIVER-SPECIFIC] erase a sector of the SPI NOR
 *			at the offset @offs
 * @priv:		the private data
 */
struct spi_nor {
	struct mtd_info		*mtd;
	struct mutex		lock;
	struct device		*dev;
	u32			page_size;
	u8			addr_width;
	u8			erase_opcode;
	u8			read_opcode;
	u8			read_dummy;
	u8			program_opcode;
	enum read_mode		flash_read;
	bool			sst_write_second;
	struct spi_nor_xfer_cfg	cfg;
	u8			cmd_buf[SPI_NOR_MAX_CMD_SIZE];

	int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
	void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
	int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
			 u8 *buf, size_t len);
	int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
			  u8 *buf, size_t len);
	int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
	int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
			int write_enable);
	const struct spi_device_id *(*read_id)(struct spi_nor *nor);
	int (*wait_till_ready)(struct spi_nor *nor);

	int (*read)(struct spi_nor *nor, loff_t from,
			size_t len, size_t *retlen, u_char *read_buf);
	void (*write)(struct spi_nor *nor, loff_t to,
			size_t len, size_t *retlen, const u_char *write_buf);
	int (*erase)(struct spi_nor *nor, loff_t offs);

	void *priv;
};
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193

/**
 * spi_nor_scan() - scan the SPI NOR
 * @nor:	the spi_nor structure
 * @id:		the spi_device_id provided by the driver
 * @mode:	the read mode supported by the driver
 *
 * The drivers can use this fuction to scan the SPI NOR.
 * In the scanning, it will try to get all the necessary information to
 * fill the mtd_info{} and the spi_nor{}.
 *
 * The board may assigns a spi_device_id with @id which be used to compared with
 * the spi_device_id detected by the scanning.
 *
 * Return: 0 for success, others for failure.
 */
int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
			enum read_mode mode);
extern const struct spi_device_id spi_nor_ids[];

194 195 196 197 198 199 200 201 202 203 204 205
/**
 * spi_nor_match_id() - find the spi_device_id by the name
 * @name:	the name of the spi_device_id
 *
 * The drivers use this function to find the spi_device_id
 * specified by the @name.
 *
 * Return: returns the right spi_device_id pointer on success,
 *         and returns NULL on failure.
 */
const struct spi_device_id *spi_nor_match_id(char *name);

206
#endif