mtd: spi-nor: add a new framework for SPI NOR
Subsystems (3)
v2 cover mtd: spi-nor: add a new framework for SPI NOR
1.) Why add a new framework for SPI NOR?
The SPI-NOR controller such as Freescale's Quadspi controller is working in a different way from the SPI bus. It should knows the NOR commands to find the right LUT sequence. Unfortunately, the current code can not meet this requirement.
2.) How does this patch set do?
This patch set adds a new spi-nor layer.
Before this patch, the layer is like:
MTD
------------------------
m25p80
------------------------
spi bus driver
------------------------
SPI NOR chipAfter this patch, the layer is like:
MTD
------------------------
spi-nor
------------------------
m25p80
------------------------
spi bus driver
------------------------
SPI NOR chipWith the spi-nor controller driver(Freescale Quadspi), it looks like:
MTD
------------------------
spi-nor
------------------------
fsl-quadspi
------------------------
SPI NOR chip3.) more details
This patch set adds a new data structrue spi_nor{}, clones most the common
code to spi-nor.c. Add spi_nor_xfer_cfg {} for the fundamental primitives:
read_xfer/write_xfer.
Make the m25p80.c use the new APIs.
Let's discuss the SPI nor framework in the new thread. :)
4.) TODO list:
3.1) add the new spi_nor_device{} for the spi-nor controller's device. 3.2) add the Freescale Quadspi driver.
v1 --> v2:
[1] follow Angus's advice, add more hooks and data structrures. [2] others.
Huang Shijie (4):
mtd: spi-nor: copy the SPI NOR commands to a new header file
mtd: spi-nor: add the basic data structures
mtd: spi-nor: add the framework for SPI NOR
mtd: m25p80: use the SPI nor framework
drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/devices/Kconfig | 2 +- drivers/mtd/devices/m25p80.c | 1261 +++-------------------------------------- drivers/mtd/spi-nor/Kconfig | 6 + drivers/mtd/spi-nor/Makefile | 1 + drivers/mtd/spi-nor/spi-nor.c | 1042 ++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 132 +++++ 8 files changed, 1277 insertions(+), 1170 deletions(-) create mode 100644 drivers/mtd/spi-nor/Kconfig create mode 100644 drivers/mtd/spi-nor/Makefile create mode 100644 drivers/mtd/spi-nor/spi-nor.c create mode 100644 include/linux/mtd/spi-nor.h
Signature · 1 line
1.7.2.rc3
PATCH v2 1/4 mtd: spi-nor: copy the SPI NOR commands to a new header file
This patch adds a new header :spi-nor.h,
and copies all the SPI NOR commands and relative macros into this new header.
This hearder can be used by the m25p80.c and other spi-nor controller, such as Freescale's Quadspi.
--- include/linux/mtd/spi-nor.h | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 53 insertions(+), 0 deletions(-) create mode 100644 include/linux/mtd/spi-nor.h
include/linux/mtd/spi-nor.h new file +53 -0
@@ -0,0 +1,53 @@ +#ifndef __LINUX_MTD_SPI_NOR_H +#define __LINUX_MTD_SPI_NOR_H + +/* Flash opcodes. */ +#define OPCODE_WREN 0x06/* Write enable */ +#define OPCODE_RDSR 0x05/* Read status register */ +#define OPCODE_WRSR 0x01/* Write status register 1 byte */ +#define OPCODE_NORM_READ 0x03/* Read data bytes (low frequency) */ +#define OPCODE_FAST_READ 0x0b/* Read data bytes (high frequency) */ +#define OPCODE_QUAD_READ 0x6b/* Read data bytes */ +#define OPCODE_PP 0x02/* Page program (up to 256 bytes) */ +#define OPCODE_BE_4K 0x20/* Erase 4KiB block */ +#define OPCODE_BE_4K_PMC 0xd7/* Erase 4KiB block on PMC chips */ +#define OPCODE_BE_32K 0x52/* Erase 32KiB block */ +#define OPCODE_CHIP_ERASE 0xc7/* Erase whole flash chip */ +#define OPCODE_SE 0xd8/* Sector erase (usually 64KiB) */ +#define OPCODE_RDID 0x9f/* Read JEDEC ID */ +#define OPCODE_RDCR 0x35/* Read configuration register */ + +/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ +#define OPCODE_NORM_READ_4B 0x13/* Read data bytes (low frequency) */ +#define OPCODE_FAST_READ_4B 0x0c/* Read data bytes (high frequency) */ +#define OPCODE_QUAD_READ_4B 0x6c/* Read data bytes */ +#define OPCODE_PP_4B 0x12/* Page program (up to 256 bytes) */ +#define OPCODE_SE_4B 0xdc/* Sector erase (usually 64KiB) */ + +/* Used for SST flashes only. */ +#define OPCODE_BP 0x02/* Byte program */ +#define OPCODE_WRDI 0x04/* Write disable */ +#define OPCODE_AAI_WP 0xad/* Auto address increment word program */ + +/* Used for Macronix and Winbond flashes. */ +#define OPCODE_EN4B 0xb7/* Enter 4-byte mode */ +#define OPCODE_EX4B 0xe9/* Exit 4-byte mode */ + +/* Used for Spansion flashes only. */ +#define OPCODE_BRWR 0x17/* Bank register write */ + +/* Status Register bits. */ +#define SR_WIP 1/* Write in progress */ +#define SR_WEL 2/* Write enable latch */ +/* meaning of other SR_* bits may differ between vendors */ +#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 */ + +#define SR_QUAD_EN_MX 0x40/* Macronix Quad I/O */ + +/* Configuration Register bits. */ +#define CR_QUAD_EN_SPAN 0x2/* Spansion Quad I/O */ + +#endif
Signature · 1 line
1.7.2.rc3
PATCH v2 2/4 mtd: spi-nor: add the basic data structures
In reply to Huang ShijieThe 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{}:
@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.
--- include/linux/mtd/spi-nor.h | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 74 insertions(+), 0 deletions(-)
include/linux/mtd/spi-nor.h +74 -0
@@ -50,4 +50,78 @@/* 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_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 +struct spi_nor { +struct mtd_info *mtd; +struct mutex lock; + +/* pointer to a spi device */ +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; + +/* for write_reg */ +u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE ]; + +/* the two fundamental primitives */ +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); + +/* write */ +void (*write)(struct spi_nor *nor,loff_t to, +size_t len,size_t *retlen,const u_char *buf); +/* read */ +int (*read)(struct spi_nor *nor,loff_t from, +size_t len,size_t *retlen,u_char *buf); +/* erase */ +int (*erase)(struct spi_nor *nor,loff_t offs); +};#endif
Signature · 1 line
1.7.2.rc3
PATCH v2 2/4 mtd: spi-nor: add the basic data structures
Quoted 46 lines · Huang Shijie
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{}:
@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_secondfor the SST NOR write.Signed-off-by Huang Shijie <[email protected]>--- include/linux/mtd/spi-nor.h | 74+++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 74 insertions(+), 0 deletions(-)
include/linux/mtd/spi-nor.h +9
-0@@ -50,4 +50,78 @@/* 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_QUAD , +}; + +/* +* struct spi_nor_xfer_cfg - Structure for defining a Serial Flash
Quoted 1 line
transfer + * @wren: command for "Write Enable", or
0x00for not
required
Quoted 42 lines
+ * @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)
+ */include/linux/mtd/spi-nor.h +32
-0+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 +struct spi_nor { +struct mtd_info *mtd; +struct mutex lock; + +/* pointer to a spi device */ +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; + +/* for write_reg */ +u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE ];
include/linux/mtd/spi-nor.h line 114
Quoted 10 lines
include/linux/mtd/spi-nor.h +10
-0+ +/* the two fundamental primitives */ +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);
Does the vybrid really support accelerated SPI NOR register IO or does it emulate it with read/write or read_xfer/write_xfer accessors ? If the later, just drop this stuff for now.
include/linux/mtd/spi-nor.h line 125
Quoted 11 lines
include/linux/mtd/spi-nor.h +11
-0+const struct spi_device_id *(*read_id)(struct spi_nor *nor); +int (*wait_till_ready)(struct spi_nor *nor); + +/* write */ +void (*write)(struct spi_nor *nor,loff_t to, +size_t len,size_t *retlen,const u_char *buf); +/* read */ +int (*read)(struct spi_nor *nor,loff_t from, +size_t len,size_t *retlen,u_char *buf); +/* erase */ +int (*erase)(struct spi_nor *nor,loff_t offs);
How do you specify what to erase (sub-sector, sector, whole chip) here ?
Quoted 2 lines
+};
#endif
PATCH v2 2/4 mtd: spi-nor: add the basic data structures
Quoted 10 lines · Marek Vasut
Quoted 9 lines · Huang Shijie
The spi_nor{} is cloned from the m25p{}.
include/linux/mtd/spi-nor.h +8
-0+struct spi_nor_xfer_cfg cfg; + +/* for write_reg */ +u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE ]; + +/* the two fundamental primitives */ +int (*read_xfer)(struct spi_nor *nor,struct spi_nor_xfer_cfg *cfg, +u8 *buf,size_t len);
Quoted 8 lines
include/linux/mtd/spi-nor.h line 114
Quoted 6 lines
include/linux/mtd/spi-nor.h +6
-0+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);Does the vybrid really support accelerated SPI NOR register IO or does it
The vybrid does not support the accelerated SPI NOR register IO. these hooks are for Lee's driver.
Quoted 2 lines
emulate it with read/write or read_xfer/write_xfer accessors ? If the later, just drop this stuff for now.
What is the "stuff" mean? the "write_enable" ?
Quoted 14 lines
include/linux/mtd/spi-nor.h line 125
Quoted 12 lines
include/linux/mtd/spi-nor.h +11
-0+const struct spi_device_id *(*read_id)(struct spi_nor *nor); +int (*wait_till_ready)(struct spi_nor *nor); + +/* write */ +void (*write)(struct spi_nor *nor,loff_t to, +size_t len,size_t *retlen,const u_char *buf); +/* read */ +int (*read)(struct spi_nor *nor,loff_t from, +size_t len,size_t *retlen,u_char *buf); +/* erase */ +int (*erase)(struct spi_nor *nor,loff_t offs);How do you specify what to erase (sub-sector, sector, whole chip) here ?
I use a write_reg(OPCODE_ERASE_CHIP) to erase the whole chip. Please read the patch 3.
This hook is used to erase a sector.
Btw, what is the sub-sector mean? which opcodes for the sub-sector?
thanks
Huang Shijie
PATCH v2 2/4 mtd: spi-nor: add the basic data structures
Quoted 20 lines · Huang Shijie
Quoted 10 lines · Marek Vasut
Quoted 9 lines · Huang Shijie
The spi_nor{} is cloned from the m25p{}.
include/linux/mtd/spi-nor.h +8
-0+struct spi_nor_xfer_cfg cfg; + +/* for write_reg */ +u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE ]; + +/* the two fundamental primitives */ +int (*read_xfer)(struct spi_nor *nor,struct spi_nor_xfer_cfg *cfg, +u8 *buf,size_t len);Quoted 8 lines
include/linux/mtd/spi-nor.h line 114
Quoted 6 lines
include/linux/mtd/spi-nor.h +6
-0+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);Does the vybrid really support accelerated SPI NOR register IO or does it
Quoted 2 lines
The vybrid does not support the accelerated SPI NOR register IO. these hooks are for Lee's driver.
Which one please?
Quoted 4 lines
Quoted 2 lines
emulate it with read/write or read_xfer/write_xfer accessors ? If the later, just drop this stuff for now.
What is the "stuff" mean? the "
write_enable" ?
This stuff -- I mean 'read SPI NOR register' and 'write SPI NOR register'. I would love to see an API which grows as needed, not an API which is bloated by unused function right from the start.
Quoted 14 lines
Quoted 5 lines
Quoted 5 lines
include/linux/mtd/spi-nor.h +5
-0+const struct spi_device_id *(*read_id)(struct spi_nor *nor); +int (*wait_till_ready)(struct spi_nor *nor); + +/* write */ + void (*write)(struct spi_nor *nor, loff_t to,Quoted 8 lines
include/linux/mtd/spi-nor.h line 125
Quoted 6 lines
include/linux/mtd/spi-nor.h +6
-0+ size_t len, size_t *retlen, const u_char *buf); +/* read */ +int (*read)(struct spi_nor *nor,loff_t from, +size_t len,size_t *retlen,u_char *buf); +/* erase */ +int (*erase)(struct spi_nor *nor,loff_t offs);How do you specify what to erase (sub-sector, sector, whole chip) here ?
Quoted 4 lines
I use a
write_reg(OPCODE_ERASE_CHIP)to erase the whole chip. Please read the patch 3.This hook is used to erase a sector.
I suspect we might need a much better documentation for this structure, it is hardly clear which function does what ;-)
Quoted 1 line
Btw, what is the sub-sector mean? which opcodes for the sub-sector?
On large chips with for example 64K big sectors, you can erase a sub-sector area, usually a 4K one. This reduces the wear of the chip. See these defines in m25p80.c :
46 #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ 48 #define OPCODE_BE_32K 0x52 /* Erase 32KiB block */ 49 #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */
Best regards,
Marek Vasut
PATCH v2 2/4 mtd: spi-nor: add the basic data structures
Quoted 18 lines
Quoted 18 lines
Quoted 17 lines
Quoted 5 lines
The spi_nor{} is cloned from the m25p{}.
include/linux/mtd/spi-nor.h +4
-0+struct spi_nor_xfer_cfg cfg; + +/* for write_reg */ +u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE ];include/linux/mtd/spi-nor.h line 114
Quoted 10 lines
include/linux/mtd/spi-nor.h +10
-0+ +/* the two fundamental primitives */ +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);Does the vybrid really support accelerated SPI NOR register IO or does it
Quoted 4 lines
Quoted 2 lines
The vybrid does not support the accelerated SPI NOR register IO. these hooks are for Lee's driver.
Which one please?
It's not in Mainline yet, but the patches are on the list.
If you search for st_spi_fsm, you'll find them.
Signature · 4 lines
Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org ? Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog
PATCH v2 2/4 mtd: spi-nor: add the basic data structures
In reply to Marek VasutQuoted 5 lines · Marek Vasut
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
include/linux/mtd/spi-nor.h +5
-0+ +/* the two fundamental primitives */ +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,
Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
include/linux/mtd/spi-nor.h line 114
Quoted 5 lines
include/linux/mtd/spi-nor.h +5
-0+ 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);This stuff -- I mean 'read SPI NOR register' and 'write SPI NOR register'. I would love to see an API which grows as needed, not an API which is bloated by unused function right from the start.
I should send out my fsl-quadspi driver in the next version.
The read_reg/write_reg are implemented by the m25p80 and fsl-quadspi now.
I think Lee's driver can implemente the read_xfer/write_xfer.
Quoted 15 lines
Quoted 15 lines
Quoted 14 lines
include/linux/mtd/spi-nor.h line 125
Quoted 12 lines
include/linux/mtd/spi-nor.h +11
-0+const struct spi_device_id *(*read_id)(struct spi_nor *nor); +int (*wait_till_ready)(struct spi_nor *nor); + +/* write */ +void (*write)(struct spi_nor *nor,loff_t to, +size_t len,size_t *retlen,const u_char *buf); +/* read */ +int (*read)(struct spi_nor *nor,loff_t from, +size_t len,size_t *retlen,u_char *buf); +/* erase */ +int (*erase)(struct spi_nor *nor,loff_t offs);How do you specify what to erase (sub-sector, sector, whole chip) here ?
Quoted 7 lines
Quoted 4 lines
I use a
write_reg(OPCODE_ERASE_CHIP)to erase the whole chip. Please read the patch 3.This hook is used to erase a sector.
I suspect we might need a much better documentation for this structure, it is hardly clear which function does what ;-)
sorry, i will add more comment in the next version.
Quoted 10 lines
Quoted 2 lines
Btw, what is the sub-sector mean? which opcodes for the sub-sector?
On large chips with for example 64K big sectors, you can erase a sub-sector area, usually a 4K one. This reduces the wear of the chip. See these defines in
m25p80.c:46 #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ 48 #define OPCODE_BE_32K 0x52 /* Erase 32KiB block */ 49 #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */
ok.
the @erase hook can be used for sub-sector too.
thanks
Huang Shijie
PATCH v2 2/4 mtd: spi-nor: add the basic data structures
Quoted 10 lines · Huang Shijie
Quoted 9 lines · Marek Vasut
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
include/linux/mtd/spi-nor.h +3
-0+ +/* the two fundamental primitives */ + int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg*cfg, + u8 *buf,
size_tlen);(quoted diff) +1
-0+ int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg*cfg, + u8 *buf,
size_tlen);(quoted diff) +2
-0+ + int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, intlen); + int (*write_reg)(struct
spi_nor*nor, u8 opcode, u8
*buf,
Quoted 6 lines
Quoted 5 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
int len, + int
write_enable);This stuff -- I mean 'read SPI NOR register' and 'write SPI NOR register'. I would love to see an API which grows as needed, not an API which is bloated by unused function right from the start.
Quoted 6 lines
I should send out my fsl-quadspi driver in the next version.
The read_reg/write_reg are implemented by the m25p80 and fsl-quadspi now.
I think Lee's driver can implemente the read_xfer/write_xfer.
OK
Quoted 18 lines
Quoted 18 lines
Quoted 18 lines
Quoted 6 lines
Quoted 6 lines
include/linux/mtd/spi-nor.h +6
-0+const struct spi_device_id *(*read_id)(struct spi_nor *nor); +int (*wait_till_ready)(struct spi_nor *nor); + +/* write */ +void (*write)(struct spi_nor *nor,loff_t to, +size_t len,size_t *retlen,const u_char *buf);Quoted 8 lines
include/linux/mtd/spi-nor.h line 125
Quoted 5 lines
include/linux/mtd/spi-nor.h +5
-0+/* read */ +int (*read)(struct spi_nor *nor,loff_t from, +size_t len,size_t *retlen,u_char *buf); +/* erase */ +int (*erase)(struct spi_nor *nor,loff_t offs);How do you specify what to erase (sub-sector, sector, whole chip) here ?
I use a
write_reg(OPCODE_ERASE_CHIP)to erase the whole chip. Please read the patch 3.
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
This hook is used to erase a sector.
I suspect we might need a much better documentation for this structure, it is hardly clear which function does what ;-)
sorry, i will add more comment in the next version.
Thanks ;-)
Quoted 6 lines
Quoted 6 lines
Quoted 1 line
Btw, what is the sub-sector mean? which opcodes for the sub-sector?
On large chips with for example 64K big sectors, you can erase a sub-sector area, usually a 4K one. This reduces the wear of the chip. See these defines in
Quoted 8 lines
Quoted 4 lines
m25p80.c:46 #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ 48 #define OPCODE_BE_32K 0x52 /* Erase 32KiB block */ 49 #define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ok.
the @erase hook can be used for sub-sector too.
I don't quite get how, but maybe you can elaborate on that one more in the next version of the patches :)
Best regards,
Marek Vasut
PATCH v2 3/4 mtd: spi-nor: add the framework for SPI NOR
In reply to Huang ShijieThis patch cloned most of the m25p80.c. In theory, it adds a new spi-nor layer.
Before this patch, the layer is like:
MTD
------------------------
m25p80
------------------------
spi bus driver
------------------------
SPI NOR chipAfter this patch, the layer is like:
MTD
------------------------
spi-nor
------------------------
m25p80
------------------------
spi bus driver
------------------------
SPI NOR chipWith the spi-nor controller driver(Freescale Quadspi), it looks like:
MTD
------------------------
spi-nor
------------------------
fsl-quadspi
------------------------
SPI NOR chipNew APIs:
spi_nor_scan: used to scan a spi-nor flash.
--- drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/spi-nor/Kconfig | 6 + drivers/mtd/spi-nor/Makefile | 1 + drivers/mtd/spi-nor/spi-nor.c | 1042 +++++++++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 5 + 6 files changed, 1057 insertions(+), 0 deletions(-) create mode 100644 drivers/mtd/spi-nor/Kconfig create mode 100644 drivers/mtd/spi-nor/Makefile create mode 100644 drivers/mtd/spi-nor/spi-nor.c
drivers/mtd/Kconfig +2 -0
@@ -320,6 +320,8 @@ source "drivers/mtd/onenand/Kconfig" source "drivers/mtd/lpddr/Kconfig" +source "drivers/mtd/spi-nor/Kconfig" + source "drivers/mtd/ubi/Kconfig" endif # MTD
drivers/mtd/Makefile +1 -0
@@ -32,4 +32,5 @@ inftl-objs := inftlcore.o inftlmount.o obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ +obj-$(CONFIG_MTD_SPI_NOR_BASE) += spi-nor/ obj-$(CONFIG_MTD_UBI) += ubi/
drivers/mtd/spi-nor/Kconfig new file +6 -0
@@ -0,0 +1,6 @@ +config MTD_SPI_NOR_BASE + bool "the framework for SPI-NOR support" + depends on MTD + help + This is the framework for the SPI NOR which can be used by the SPI + device drivers and the SPI-NOR device driver.
drivers/mtd/spi-nor/Makefile new file +1 -0
@@ -0,0 +1 @@ +obj-$(CONFIG_MTD_SPI_NOR_BASE) += spi-nor.o
drivers/mtd/spi-nor/spi-nor.c new file +1042 -0
1,042 lines not on this page · raw message
include/linux/mtd/spi-nor.h +5 -0
@@ -124,4 +124,9 @@ struct spi_nor {/* erase */ int (*erase)(struct spi_nor *nor, loff_t offs); }; + +int spi_nor_scan (struct spi_nor *nor,const struct spi_device_id *id, +bool quad_read); +extern const struct spi_device_id spi_nor_ids[]; +#endif
Signature · 1 line
1.7.2.rc3
PATCH 1/1 mtd: m25p80: use the SPI nor framework
In reply to Huang ShijieUse the new SPI nor framework, and rewrite the m25p80:
(0) remove all the NOR comands.
(1) change the m25p->command to an array.
(2) implement the necessary hooks, such as m25p_read/m25p_write.
Tested with the m25p32.
--- drivers/mtd/devices/Kconfig | 2 +- drivers/mtd/devices/m25p80.c | 1269 +++--------------------------------------- 2 files changed, 93 insertions(+), 1178 deletions(-)
drivers/mtd/devices/Kconfig +1 -1
@@ -80,7 +80,7 @@ config MTD_DATAFLASH_OTP config MTD_M25P80 tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)" - depends on SPI_MASTER + depends on SPI_MASTER && MTD_SPI_NOR_BASE help This enables access to most modern SPI flash chips, used for program and data storage. Series supported include Atmel AT26DF,
drivers/mtd/devices/m25p80.c +92 -1177
1,377 lines not on this page · raw message
Signature · 1 line
1.7.2.rc3
v2 cover mtd: spi-nor: add a new framework for SPI NOR
In reply to Huang ShijieHi Huang,
Quoted 71 lines · Huang Shijie
1.) Why add a new framework for SPI NOR?
The SPI-NOR controller such as Freescale's Quadspi controller is working in a different way from the SPI bus. It should knows the NOR commands to find the right LUT sequence. Unfortunately, the current code can not meet this requirement.2.) How does this patch set do?
This patch set adds a new spi-nor layer. Before this patch, the layer is like: MTD ------------------------ m25p80 ------------------------ spi bus driver ------------------------ SPI NOR chip After this patch, the layer is like: MTD ------------------------ spi-nor ------------------------ m25p80 ------------------------ spi bus driver ------------------------ SPI NOR chipWith the spi-nor controller driver(Freescale Quadspi), it looks like: MTD ------------------------ spi-nor ------------------------ fsl-quadspi ------------------------ SPI NOR chip3.) more details
This patch set adds a new data structrue spi_nor{}, clones most the common
code tospi-nor.c. Addspi_nor_xfer_cfg{} for the fundamental primitives:
read_xfer/write_xfer.Make the
m25p80.cuse the new APIs.Let's discuss the SPI nor framework in the new thread. :)
4.) TODO list:
3.1) add the new spi_nor_device{} for the spi-nor controller's device. 3.2) add the Freescale Quadspi driver.v1 --> v2:
[1] follow Angus's advice, add more hooks and data structrures. [2] others.Huang Shijie (4):
mtd: spi-nor: copy the SPI NOR commands to a new header file
mtd: spi-nor: add the basic data structures
mtd: spi-nor: add the framework for SPI NOR
mtd: m25p80: use the SPI nor frameworkdrivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/devices/Kconfig | 2 +- drivers/mtd/devices/m25p80.c | 1261 +++-------------------------------------- drivers/mtd/spi-nor/Kconfig | 6 + drivers/mtd/spi-nor/Makefile | 1 + drivers/mtd/spi-nor/spi-nor.c | 1042 ++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 132 +++++ 8 files changed, 1277 insertions(+), 1170 deletions(-)
Quoted 5 lines
create mode 100644
drivers/mtd/spi-nor/Kconfigcreate mode 100644drivers/mtd/spi-nor/Makefilecreate mode 100644drivers/mtd/spi-nor/spi-nor.ccreate mode 100644include/linux/mtd/spi-nor.h
I have a requirement for a memory mapped operation for my spi flash driver.
A brief explanation about the requirement is here..
ti qspi supports two modes of operation, one is SPI mode(normal), other is the memory mapped read mode.
For SPI mode, the state machine remains the same as it is with other spi controller
available.
For memory mapped, there is something more which we need to do around ..
1. There is a qspi "set up" register available, which needs to be filled with
information like flash opcode, dummy bytes etc. In short, flash
specific
details.
2 if the above register is configured with the required opcodes, then
whenever
we need to use memory mapped operations, we need to do is to
switch our
qspi controller to memory mapped mode.
Switching of this mode to memory mapped needs
a ) write to a particular qspi register
b) write to control module(optional based on SOC).
3. Once the above steps are configured, then the flash data will be mapped to a
particular memory address(SOC specific) from where the flash data
can be read.
The series
https://www.mail-archive.com/linux-omap at vger.kernel.org/msg98691.html tries to work on the above features, and tries to add a support for the same in the
spi framework and m25p80 code.
As you see in my patches, once we take care of the above points and add support
for memory mapped in m25p80 and qspi, then while doing a read in m25p80 we can
do memcpy at the beginning of m25p80_read and can bypass the entire SPI framework for memory mapped read operation. Throughput almost gets doubles with this,
as compared to normal SPI operations.
So, my intention of reviving this here is to add one more feature set, which I suppose
spi nor framework should handle and to see what needs to be added more for this feature.
Please get back, if you need more info on this concept.
v2 cover mtd: spi-nor: add a new framework for SPI NOR
Quoted 9 lines · Sourav Poddar
As you see in my patches, once we take care of the above points and add support
for memory mapped in m25p80 and qspi, then while doing a read in m25p80 we can
do memcpy at the beginning ofm25p80_readand can bypass the entire SPI framework for memory mapped read operation. Throughput almost gets doubles with this,
as compared to normal SPI operations.
Quoted 4 lines
So, my intention of reviving this here is to add one more feature set, which I suppose
spi nor framework should handle and to see what needs to be added more for this feature.
I already read your patch.
My quadspi driver also uses the memory map mode.
The memory map mode is the default mode for the quadspi driver's read.
You can setup the registers for memory map in the probe() or some other places. And use the spi_nor->read() hook to do the memcpy in your driver.
thanks
Huang Shijie
v2 cover mtd: spi-nor: add a new framework for SPI NOR
Quoted 17 lines · Huang Shijie
Quoted 9 lines · Sourav Poddar
As you see in my patches, once we take care of the above points and add support
for memory mapped in m25p80 and qspi, then while doing a read in m25p80 we can
do memcpy at the beginning ofm25p80_readand can bypass the entire SPI framework for memory mapped read operation. Throughput almost gets doubles with this,
as compared to normal SPI operations.Quoted 4 lines
So, my intention of reviving this here is to add one more feature set, which I suppose
spi nor framework should handle and to see what needs to be added more for this feature.I already read your patch.
Quoted 7 lines
My quadspi driver also uses the memory map mode.
The memory map mode is the default mode for the quadspi driver's read.You can setup the registers for memory map in the
probe()or some other places. And use thespi_nor->read()hook to do the memcpy in your driver.
So, setting these registers should be set in my qspi controller driver in spi layer.
There registers requires flash opcodes and other flash specific parameters. I dont intend
to get this from dt, so need this information to be send via the mtd layer. So, dont think if
the present hooks will help me out.
Secondly, I had a dependency on few registers to switch between memory mapped mode and
spi mode. So, even though read is by default memory mapped, I need to write to qspi register
to switch to memory mapped mode and once the read is done, switch the controller back to
SPI mode.
So all in all, some hooks like
- configure_master_from_slave
- enable_mmap/disable_mmap is desired.
Do you think, we can handle/integrate this case in the above framework?
Quoted 3 lines
thanks
Huang Shijie