
Hi Jagan,
On 30 October 2016 at 12:23, Jagan Teki jagan@openedev.com wrote:
Some of the SPI device drivers at drivers/spi not a real spi controllers, Unlike normal/generic SPI controllers they operates only with SPI-NOR flash devices. these were technically termed as SPI-NOR controllers, Ex: drivers/spi/fsl_qspi.c
The problem with these were resides at drivers/spi is entire SPI layer becomes SPI-NOR flash oriented which is absolutely a wrong indication where SPI layer getting effected more with flash operations - So this SPI-NOR core will resolve this issue by separating all SPI-NOR flash operations from spi layer and creats a generic layer called SPI-NOR core which can be used to interact SPI-NOR to SPI driver interface layer and the SPI-NOR controller driver. The idea is taken from Linux spi-nor framework.
cmd_sf.c
mtd-uclass
SPI-NOR Core
m25p80.c zynq_qspi
spi-uclass SPI NOR chip
spi drivers
SPI NOR chip
Signed-off-by: Jagan Teki jagan@openedev.com
Makefile | 1 + drivers/mtd/spi-nor/Makefile | 9 + drivers/mtd/spi-nor/spi-nor-ids.c | 176 +++++++++++ drivers/mtd/spi-nor/spi-nor.c | 648 ++++++++++++++++++++++++++++++++++++++ include/linux/err.h | 5 + include/linux/mtd/spi-nor.h | 207 ++++++++++++ 6 files changed, 1046 insertions(+) create mode 100644 drivers/mtd/spi-nor/Makefile create mode 100644 drivers/mtd/spi-nor/spi-nor-ids.c create mode 100644 drivers/mtd/spi-nor/spi-nor.c create mode 100644 include/linux/mtd/spi-nor.h
[...]
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h new file mode 100644 index 0000000..4e5b3ba --- /dev/null +++ b/include/linux/mtd/spi-nor.h @@ -0,0 +1,207 @@ +/*
- SPI NOR Core header file.
- Copyright (C) 2016 Jagan Teki jagan@openedev.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __MTD_SPI_NOR_H +#define __MTD_SPI_NOR_H
+#include <common.h>
+/*
- Manufacturer IDs
- The first byte returned from the flash after sending opcode SPINOR_OP_RDID.
- Sometimes these are the same as CFI IDs, but sometimes they aren't.
- */
+#define SNOR_MFR_ATMEL 0x1f +#define SNOR_MFR_MACRONIX 0xc2 +#define SNOR_MFR_MICRON 0x20 /* ST Micro <--> Micron */ +#define SNOR_MFR_SPANSION 0x01 +#define SNOR_MFR_SST 0xbf +#define SNOR_MFR_WINBOND 0xef
+/**
- SPI NOR opcodes.
- Note on opcode nomenclature: some opcodes have a format like
- SNOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
- of I/O lines used for the opcode, address, and data (respectively). The
- FUNCTION has an optional suffix of '4', to represent an opcode which
- requires a 4-byte (32-bit) address.
- */
+#define SNOR_OP_WRDI 0x04 /* Write disable */ +#define SNOR_OP_WREN 0x06 /* Write enable */ +#define SNOR_OP_RDSR 0x05 /* Read status register */ +#define SNOR_OP_WRSR 0x01 /* Write status register 1 byte */ +#define SNOR_OP_READ 0x03 /* Read data bytes (low frequency) */ +#define SNOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ +#define SNOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */ +#define SNOR_OP_READ_1_1_2_IO 0xbb /* Read data bytes (Dual IO SPI) */ +#define SNOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */ +#define SNOR_OP_READ_1_1_4_IO 0xeb /* Read data bytes (Quad IO SPI) */ +#define SNOR_OP_BRWR 0x17 /* Bank register write */ +#define SNOR_OP_BRRD 0x16 /* Bank register read */ +#define SNOR_OP_WREAR 0xC5 /* Write extended address register */ +#define SNOR_OP_RDEAR 0xC8 /* Read extended address register */ +#define SNOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ +#define SNOR_OP_QPP 0x32 /* Quad Page program */ +#define SNOR_OP_BE_4K 0x20 /* Erase 4KiB block */ +#define SNOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ +#define SNOR_OP_BE_32K 0x52 /* Erase 32KiB block */ +#define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */ +#define SNOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */ +#define SNOR_OP_RDID 0x9f /* Read JEDEC ID */ +#define SNOR_OP_RDCR 0x35 /* Read configuration register */ +#define SNOR_OP_RDFSR 0x70 /* Read flag status register */
+/* Used for SST flashes only. */ +#define SNOR_OP_BP 0x02 /* Byte program */ +#define SNOR_OP_AAI_WP 0xad /* Auto addr increment word program */
+/* Status Register bits. */ +#define SR_WIP BIT(0) /* Write in progress */ +#define SR_WEL BIT(1) /* Write enable latch */
+/* meaning of other SR_* bits may differ between vendors */ +#define SR_BP0 BIT(2) /* Block protect 0 */ +#define SR_BP1 BIT(3) /* Block protect 1 */ +#define SR_BP2 BIT(4) /* Block protect 2 */ +#define SR_SRWD BIT(7) /* SR write protect */
+#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */
+/* Flag Status Register bits */ +#define FSR_READY BIT(7)
+/* Configuration Register bits. */ +#define CR_QUAD_EN_SPAN BIT(1) /* Spansion/Winbond Quad I/O */
+/* Flash timeout values */ +#define SNOR_READY_WAIT_PROG (2 * CONFIG_SYS_HZ) +#define SNOR_READY_WAIT_ERASE (5 * CONFIG_SYS_HZ) +#define SNOR_MAX_CMD_SIZE 4 +#define SNOR_16MB_BOUN 0x1000000
+enum snor_option_flags {
SNOR_F_SST_WRITE = BIT(0),
SNOR_F_USE_FSR = BIT(1),
SNOR_F_U_PAGE = BIT(1),
+};
+enum mode {
SNOR_READ = BIT(0),
SNOR_READ_1_1_2 = BIT(1),
SNOR_READ_1_1_4 = BIT(2),
SNOR_READ_1_1_2_IO = BIT(3),
SNOR_READ_1_1_4_IO = BIT(4),
SNOR_WRITE_1_1_BYTE = BIT(5),
SNOR_WRITE_1_1_4 = BIT(6),
+};
+#define JEDEC_MFR(info) ((info)->id[0]) +#define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) +#define JEDEC_EXT(info) (((info)->id[3]) << 8 | ((info)->id[4])) +#define SPI_NOR_MAX_ID_LEN 6
+struct spi_nor_info {
char *name;
/*
* This array stores the ID bytes.
* The first three bytes are the JEDIC ID.
* JEDEC ID zero means "no ID" (mostly older chips).
*/
u8 id[SPI_NOR_MAX_ID_LEN];
u8 id_len;
/* The size listed here is what works with SNOR_OP_SE, which isn't
* necessarily called a "sector" by the vendor.
*/
unsigned sector_size;
u16 n_sectors;
u16 page_size;
u16 flags;
+#define SECT_4K BIT(0) +#define E_FSR BIT(1) +#define SST_WR BIT(2) +#define WR_QPP BIT(3) +#define RD_QUAD BIT(4) +#define RD_DUAL BIT(5) +#define RD_QUADIO BIT(6) +#define RD_DUALIO BIT(7) +#define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) +};
+extern const struct spi_nor_info spi_nor_ids[];
+/**
- struct spi_nor - Structure for defining a the SPI NOR layer
- @dev: SPI NOR device
- @name: name of the SPI NOR 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 bytes needed by the read operation
- @program_opcode: the program opcode
- @max_write_size: If non-zero, the maximum number of bytes which can
be written at once, excluding command bytes.
- @flags: flag options for the current SPI-NOR (SNOR_F_*)
- @mode: read, write mode or any other mode bits.
- @read_mode: read mode.
- @cmd_buf: used by the write_reg
- @read_reg: [DRIVER-SPECIFIC] read out the register
- @write_reg: [DRIVER-SPECIFIC] write data to the register
- @read: [DRIVER-SPECIFIC] read data from the SPI NOR
- @write: [DRIVER-SPECIFIC] write data to the SPI NOR
- @memory_map: address of read-only SPI NOR access
- @priv: the private data
- */
+struct spi_nor {
struct udevice *dev;
const char *name;
u32 page_size;
u8 addr_width;
u8 erase_opcode;
u8 read_opcode;
u8 read_dummy;
u8 program_opcode;
u32 max_write_size;
u32 flags;
u8 mode;
u8 read_mode;
u8 cmd_buf[SNOR_MAX_CMD_SIZE];
int (*read_reg)(struct spi_nor *nor, u8 cmd, u8 *val, int len);
int (*write_reg)(struct spi_nor *nor, u8 cmd, u8 *data, int len);
int (*read)(struct spi_nor *nor, loff_t from, size_t len,
u_char *read_buf);
int (*write)(struct spi_nor *nor, loff_t to, size_t len,
const u_char *write_buf);
Sos is SPI_NOR a uclass? It seems like you have different drivers for it, and so it should be. Perhaps the SPI_NOR uclass should be a child of the MTD uclass?
void *memory_map;
void *priv;
+};
+/**
- spi_nor_scan() - scan the SPI NOR
- @dev: SPI NOR device
- 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{}.
- @return 0 if OK, -ve on error
- */
+int spi_nor_scan(struct udevice *dev);
+#endif /* __MTD_SPI_NOR_H */
2.7.4
Regards, Simon