mtd: spi-nor: add the basic data structures
authorHuang Shijie <b32955@freescale.com>
Mon, 24 Feb 2014 10:37:36 +0000 (18:37 +0800)
committerBrian Norris <computersforpeace@gmail.com>
Mon, 14 Apr 2014 18:22:58 +0000 (11:22 -0700)
The spi_nor{} is cloned from the m25p{}.
The spi_nor{} can be used by both the m25p80 and spi-nor controller.

We also add the spi_nor_xfer_cfg{} which can be used by the two
fundamental primitives: read_xfer/write_xfer.

 1) the hooks for spi_nor{}:
    @prepare/unpreare: used to do some work before or after the
             read/write/erase/lock/unlock.
    @read_xfer/write_xfer: We can use these two hooks to code all
             the following hooks if the driver tries to implement them
             by itself.
    @read_reg: used to read the registers, such as read status register,
             read configure register.
    @write_reg: used to write the registers, such as write enable,
             erase sector.
    @read_id: read out the ID info.
    @wait_till_ready: wait till the NOR becomes ready.
    @read: read out the data from the NOR.
    @write: write data to the NOR.
    @erase: erase a sector of the NOR.

 2) Add a new field sst_write_second for the SST NOR write.

Signed-off-by: Huang Shijie <b32955@freescale.com>
Acked-by: Marek Vasut <marex@denx.de>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
include/linux/mtd/spi-nor.h

index 483fc2a..3a3c387 100644 (file)
 /* Configuration Register bits. */
 #define CR_QUAD_EN_SPAN                0x2     /* Spansion Quad I/O */
 
+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;
+};
+
+#define        SPI_NOR_MAX_CMD_SIZE    8
+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;
+};
 #endif