mtd: spi-nor: add a new framework for SPI NOR
Subsystems (4)
v3 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/fsl_quaspi.c use the new APIs.
4.) Change log:
v2 --> v3:
[1] add prepare/unprepare hooks for spi_nor{}.
[2] add a new "priv" field for spi_nor{}.
[3] add the Freescale Quadspi driver which supports the Quad read by default.
v1 --> v2:
[1] follow Angus's advice, add more hooks and data structrures. [2] others.
Huang Shijie (7):
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
mtd: spi-nor: add a helper to find the spi_device_id
Documentation: add the binding file for Quadspi driver
mtd: spi-nor: Add Freescale QuadSpi driver
.../devicetree/bindings/mtd/fsl-quadspi.txt | 31 + drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/devices/Kconfig | 2 +- drivers/mtd/devices/m25p80.c | 1271 ++------------------ drivers/mtd/spi-nor/Kconfig | 12 + drivers/mtd/spi-nor/Makefile | 2 + drivers/mtd/spi-nor/fsl-quadspi.c | 927 ++++++++++++++ drivers/mtd/spi-nor/spi-nor.c | 1098 +++++++++++++++++ include/linux/mtd/spi-nor.h | 167 +++ 10 files changed, 2335 insertions(+), 1178 deletions(-) create mode 100644 Documentation/devicetree/bindings/mtd/fsl-quadspi.txt create mode 100644 drivers/mtd/spi-nor/Kconfig create mode 100644 drivers/mtd/spi-nor/Makefile create mode 100644 drivers/mtd/spi-nor/fsl-quadspi.c 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 v3 1/7 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 v3 1/7 mtd: spi-nor: copy the SPI NOR commands to a new header file
Quoted 8 lines · Huang Shijie
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.cand other spi-nor controller, such as Freescale's Quadspi.Signed-off-by Huang Shijie <[email protected]>
It would be much nicer if you also removed the commands in this same patch from the m25p80.c file.
Best regards,
Marek Vasut
PATCH v3 1/7 mtd: spi-nor: copy the SPI NOR commands to a new header file
Quoted 5 lines · Marek Vasut
Quoted 4 lines · Huang Shijie
This patch adds a new header :spi-nor.h,
and copies all the SPI NOR commands and relative macros into this new header.
Quoted 7 lines
Quoted 4 lines
This hearder can be used by the
m25p80.cand other spi-nor controller, such as Freescale's Quadspi.Signed-off-by Huang Shijie <[email protected]>It would be much nicer if you also removed the commands in this same patch from the
m25p80.cfile.
my earlier version did so. :)
So keep it as it is now.
thanks
Huang Shijie
PATCH v3 2/7 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{}:
@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.
--- include/linux/mtd/spi-nor.h | 108 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 108 insertions(+), 0 deletions(-)
include/linux/mtd/spi-nor.h +108 -0
@@ -50,4 +50,112 @@/* 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 +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 { +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 ]; + +/* +* Do some work before or after we run these operations: +* read/write/erese/lock/unlock +*/ +int (*prepare)(struct spi_nor *nor,enum spi_nor_ops ops); +void (*unprepare)(struct spi_nor *nor,enum spi_nor_ops ops); + +/* +* The two fundamental primitives, you can use them to implement +* all the other hooks, except the prepare/unprepare. +*/ +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); + +/* +* The two hooks are used to read/write SPI NOR register, such as +* read status register, write status register. +*/ +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); + +/* +* The hook for reading out the ID, the spi-nor controller drivers +* can fill it with its own implementation if the default +* could not meet its requirement. +*/ +const struct spi_device_id *(*read_id)(struct spi_nor *nor); + +/* +* The hook for "Wait till ready", some spi-nor controller drivers +* may fill it with its own implementation. +*/ +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 a sector(4K/64K, etc..) */ +int (*erase)(struct spi_nor *nor,loff_t offs); + +void *priv; +};#endif
Signature · 1 line
1.7.2.rc3
PATCH v3 2/7 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{}:
@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_secondfor the SST NOR write.Signed-off-by Huang Shijie <[email protected]>--- include/linux/mtd/spi-nor.h | 108+++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 108 insertions(+), 0 deletions(-)
include/linux/mtd/spi-nor.h +8
-0@@ -50,4 +50,112 @@/* 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 37 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 +27
-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 +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 { +struct mtd_info *mtd; +struct mutex lock; + +/* pointer to a spi device */
include/linux/mtd/spi-nor.h line 108
Quoted 10 lines
include/linux/mtd/spi-nor.h +10
-0+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;
You do want to split the function pointers below and the device configuration above into separate structures.
include/linux/mtd/spi-nor.h line 115
Quoted 6 lines
include/linux/mtd/spi-nor.h +6
-0+/* for write_reg */ +u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE ]; + +/* +* Do some work before or after we run these operations: +* read/write/erese/lock/unlock
Proper kernel-doc style comments for this structure would be nice.
Quoted 7 lines
include/linux/mtd/spi-nor.h +7
-0+*/ +int (*prepare)(struct spi_nor *nor,enum spi_nor_ops ops); +void (*unprepare)(struct spi_nor *nor,enum spi_nor_ops ops); + +/* +* The two fundamental primitives, you can use them to implement +* all the other hooks, except the prepare/unprepare.
include/linux/mtd/spi-nor.h line 132
Quoted 10 lines
include/linux/mtd/spi-nor.h +10
-0+*/ +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); + +/* +* The two hooks are used to read/write SPI NOR register, such as +* read status register, write status register. +*/
The format of the comment is messed up, please fix globally.
Quoted 8 lines
include/linux/mtd/spi-nor.h +8
-0+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); + +/* +* The hook for reading out the ID, the spi-nor controller drivers +* can fill it with its own implementation if the default +* could not meet its requirement.
include/linux/mtd/spi-nor.h line 150
Quoted 10 lines
include/linux/mtd/spi-nor.h +10
-0+*/ +const struct spi_device_id *(*read_id)(struct spi_nor *nor); + +/* +* The hook for "Wait till ready", some spi-nor controller drivers +* may fill it with its own implementation. +*/ +int (*wait_till_ready)(struct spi_nor *nor); + +/* write */
write ... what ? I get it, but a proper documentation for new API would be _nice_ . Besides, I do not understand the parameters at all. Neither do I understand how to implement driver based on this API.
include/linux/mtd/spi-nor.h line 156
Quoted 6 lines
include/linux/mtd/spi-nor.h +6
-0+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 a sector(4K/64K, etc..) */
How do you select the erase size here (this is not documented, I dont understand it at all)?
Quoted 5 lines
include/linux/mtd/spi-nor.h +4
-0+int (*erase)(struct spi_nor *nor,loff_t offs); + + void *priv; +};#endif
PATCH v3 2/7 mtd: spi-nor: add the basic data structures
Quoted 10 lines · Marek Vasut
Quoted 9 lines · Huang Shijie
include/linux/mtd/spi-nor.h +9
-0+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;
Quoted 8 lines
include/linux/mtd/spi-nor.h line 108
Quoted 5 lines
include/linux/mtd/spi-nor.h +5
-0+u8 read_dummy; +u8 program_opcode; +enum read_mode flash_read; +bool sst_write_second; +struct spi_nor_xfer_cfg cfg;You do want to split the function pointers below and the device configuration above into separate structures.
sorry, i prefer to keep them in one data structrue, just like the nand_chip{} does.
Quoted 9 lines
include/linux/mtd/spi-nor.h line 115
Quoted 7 lines
include/linux/mtd/spi-nor.h +6
-0+/* for write_reg */ +u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE ]; + +/* +* Do some work before or after we run these operations: +* read/write/erese/lock/unlock Proper kernel-doc style comments for this structure would be nice.
Do you mean the style used by nand_chip{}?
thanks
Huang Shijie
PATCH v3 2/7 mtd: spi-nor: add the basic data structures
Quoted 20 lines · Huang Shijie
Quoted 10 lines · Marek Vasut
Quoted 9 lines · Huang Shijie
include/linux/mtd/spi-nor.h +9
-0+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;Quoted 8 lines
include/linux/mtd/spi-nor.h line 108
Quoted 5 lines
include/linux/mtd/spi-nor.h +5
-0+u8 read_dummy; +u8 program_opcode; +enum read_mode flash_read; +bool sst_write_second; +struct spi_nor_xfer_cfg cfg;You do want to split the function pointers below and the device configuration above into separate structures.
Quoted 2 lines
sorry, i prefer to keep them in one data structrue, just like the nand_chip{} does.
Can you explain why?
Quoted 10 lines
Quoted 8 lines
include/linux/mtd/spi-nor.h line 115
Quoted 6 lines
include/linux/mtd/spi-nor.h +6
-0+/* for write_reg */ +u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE ]; + +/* +* Do some work before or after we run these operations: +* read/write/erese/lock/unlock Proper kernel-doc style comments for this structure would be nice.
Do you mean the style used by nand_chip{}?
Yes. See Documentation/kernel-doc-nano-HOWTO.txt
Best regards,
Marek Vasut
PATCH v3 2/7 mtd: spi-nor: add the basic data structures
Quoted 21 lines · Marek Vasut
Quoted 20 lines · Huang Shijie
Quoted 18 lines · Marek Vasut
Quoted 4 lines · Huang Shijie
include/linux/mtd/spi-nor.h +4
-0+struct spi_nor { > > + struct mtd_info *mtd; +struct mutex lock; + +/* pointer to a spi device */ include/linux/mtd/spi-nor.h line 108
Quoted 10 lines
include/linux/mtd/spi-nor.h +10
-0+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;You do want to split the function pointers below and the device configuration above into separate structures.
Quoted 3 lines
Quoted 2 lines
sorry, i prefer to keep them in one data structrue, just like the nand_chip{} does.
Take @read_reg for example, currently, we call it with nor->read_reg(); If we add a new data structrue for these hooks, we wil call it with nor->ops->read_reg().
So just like the nand_chip{}, make the code more simple.
thanks
Huang Shijie
PATCH v3 3/7 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 | 1086 +++++++++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 5 + 6 files changed, 1101 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 +1086 -0
1,086 lines not on this page · raw message
include/linux/mtd/spi-nor.h +5 -0
@@ -158,4 +158,9 @@ struct spi_nor { void *priv; }; + +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[]; +#endif
Signature · 1 line
1.7.2.rc3
PATCH v3 3/7 mtd: spi-nor: add the framework for SPI NOR
Quoted 743 lines · Huang Shijie
This 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.Signed-off-by Huang Shijie<[email protected]>--- 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 | 1086 +++++++++++++++++++++++++++++++++++++++++ include/linux/mtd/spi-nor.h | 5 + 6 files changed, 1101 insertions(+), 0 deletions(-)create mode 100644
drivers/mtd/spi-nor/Kconfigcreate mode 100644drivers/mtd/spi-nor/Makefilecreate mode 100644drivers/mtd/spi-nor/spi-nor.cdrivers/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 # MTDdrivers/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.odrivers/mtd/spi-nor/spi-nor.c new file +647
-0@@ -0,0 +1,1086 @@ +/* +* Cloned most of the code from the m25p80.c +* +* This code is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 as +* published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/mutex.h> +#include <linux/math64.h> +#include <linux/slab.h> +#include <linux/sched.h> +#include <linux/mod_devicetable.h> + +#include <linux/mtd/cfi.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/of_platform.h> +#include <linux/spi/flash.h> +#include <linux/mtd/spi-nor.h> + +/* Define max times to check status register before we give up. */ +#define MAX_READY_WAIT_JIFFIES (40 * HZ)/* M25P16 specs 40s max chip erase */ + +#define JEDEC_MFR (_jedec_id) ((_jedec_id)>> 16) + +/* +* Read the status register, returning its value in the location +* Return the status register value. +* Returns negative if error occurred. +*/ +static int read_sr (struct spi_nor *nor) +{ +int ret; +u8 val; + + ret = nor->read_reg (nor,OPCODE_RDSR ,&val,1 ); +if (ret<0 ) { +pr_err ("error %d reading SR\n" , (int ) ret); +return ret; + } + +return val; +} + +/* +* Read configuration register, returning its value in the +* location. Return the configuration register value. +* Returns negative if error occured. +*/ +static int read_cr (struct spi_nor *nor) +{ +int ret; +u8 val; + + ret = nor->read_reg (nor,OPCODE_RDCR ,&val,1 ); +if (ret<0 ) { +dev_err (nor->dev,"error %d reading CR\n" , ret); +return ret; + } + +return val; +} + +/* +* Dummy Cycle calculation for different type of read. +* It can be used to support more commands with +* different dummy cycle requirements. +*/ +static inline int spi_nor_read_dummy_cycles (struct spi_nor *nor) +{ +switch (nor->flash_read) { +case SPI_NOR_FAST : +case SPI_NOR_QUAD : +return 1 ; +case SPI_NOR_NORMAL : +return 0 ; + } +return 0 ; +} + +/* +* Write status register 1 byte +* Returns negative if error occurred. +*/ +static inline int write_sr (struct spi_nor *nor,u8 val) +{ + nor->cmd_buf[0 ] = val; +return nor->write_reg (nor,OPCODE_WRSR , nor->cmd_buf,1 ,0 ); +} + +/* +* Set write enable latch with Write Enable command. +* Returns negative if error occurred. +*/ +static inline int write_enable (struct spi_nor *nor) +{ +return nor->write_reg (nor,OPCODE_WREN ,NULL ,0 ,0 ); +} + +/* +* Write status Register and configuration register with 2 bytes +* The first byte will be written to the status register, while the +* second byte will be written to the configuration register. +* Return negative if error occured. +*/ +static int write_sr_cr (struct spi_nor *nor,u16 val) +{ + nor->cmd_buf[0 ] = val&0xff ; + nor->cmd_buf[1 ] = (val>>8 ); + +return nor->write_reg (nor,OPCODE_WRSR , nor->cmd_buf,2 ,0 ); +} + +/* +* Send write disble instruction to the chip. +*/ +static inline int write_disable (struct spi_nor *nor) +{ +return nor->write_reg (nor,OPCODE_WRDI ,NULL ,0 ,0 ); +} + +static inline struct spi_nor *mtd_to_spi_nor (struct mtd_info *mtd) +{ +return mtd->priv; +} + +/* Enable/disable 4-byte addressing mode. */ +static inline int set_4byte (struct spi_nor *nor,u32 jedec_id,int enable) +{ +int status; +bool need_wren = false; +u8 cmd; + +switch (JEDEC_MFR (jedec_id)) { +case CFI_MFR_ST :/* Micron, actually */ +/* Some Micron need WREN command; all will accept it */ + need_wren = true; +case CFI_MFR_MACRONIX : +case 0xEF /* winbond */ : +if (need_wren) +write_enable (nor); + + cmd = enable ?OPCODE_EN4B :OPCODE_EX4B ; + status = nor->write_reg (nor, cmd,NULL ,0 ,0 ); +if (need_wren) +write_disable (nor); + +return status; +default : +/* Spansion style */ + nor->cmd_buf[0 ] = enable<<7 ; +return nor->write_reg (nor,OPCODE_BRWR , nor->cmd_buf,1 ,0 ); + } +} + +static int spi_nor_wait_till_ready (struct spi_nor *nor) +{ +unsigned long deadline; +int sr; + + deadline = jiffies +MAX_READY_WAIT_JIFFIES ; + +do { +cond_resched (); + +if ((sr =read_sr (nor))<0 ) +break ; +else if (!(sr&SR_WIP )) +return 0 ; + }while (!time_after_eq (jiffies, deadline)); + +return -ETIMEDOUT ; +} + +/* +* Service routine to read status register until ready, or timeout occurs. +* Returns non-zero if error. +*/ +static int wait_till_ready (struct spi_nor *nor) +{ +return nor->wait_till_ready (nor); +} + +/* +* Erase the whole flash memory +* +* Returns 0 if successful, non-zero otherwise. +*/ +static int erase_chip (struct spi_nor *nor) +{ +int ret; + +dev_dbg (nor->dev," %lldKiB\n" , (long long )(nor->mtd->size>>10 )); + +/* Wait until finished previous write command. */ + ret =wait_till_ready (nor); +if (ret) +return ret; + +/* Send write enable, then erase commands. */ +write_enable (nor); + +return nor->write_reg (nor,OPCODE_CHIP_ERASE ,NULL ,0 ,0 ); +} + +static int spi_nor_lock_and_prep (struct spi_nor *nor,enum spi_nor_ops ops) +{ +int ret =0 ; + +mutex_lock (&nor->lock); + +if (nor->prepare) { + ret = nor->prepare (nor, ops); +if (ret) { +dev_err (nor->dev,"failed in the preparation.\n" ); +mutex_unlock (&nor->lock); +return ret; + } + } +return ret; +} + +static void spi_nor_unlock_and_unprep (struct spi_nor *nor,enum spi_nor_ops ops) +{ +if (nor->unprepare) + nor->unprepare (nor, ops); +mutex_unlock (&nor->lock); +} + +/* +* Erase an address range on the nor chip. The address range may extend +* one or more erase sectors. Return an error is there is a problem erasing. +*/ +static int spi_nor_erase (struct mtd_info *mtd,struct erase_info *instr) +{ +struct spi_nor *nor =mtd_to_spi_nor (mtd); +u32 addr,len; +uint32_t rem; +int ret; + +dev_dbg (nor->dev,"at 0x%llx, len %lld\n" , (long long )instr->addr, + (long long )instr->len); + +div_u64_rem (instr->len, mtd->erasesize,&rem); +if (rem) +return -EINVAL ; + + addr = instr->addr; + len = instr->len; + + ret =spi_nor_lock_and_prep (nor,SPI_NOR_OPS_ERASE ); +if (ret) +return ret; + +/* whole-chip erase? */ +if (len == mtd->size) { +if (erase_chip (nor)) { + ret = -EIO ; + goto erase_err; + } + +/* REVISIT in some cases we could speed up erasing large regions +* by using OPCODE_SE instead of OPCODE_BE_4K. We may have set up +* to use "small sector erase", but that's not always optimal. +*/ + +/* "sector"-at-a-time erase */ + }else { +while (len) { +if (nor->erase (nor, addr)) { + ret = -EIO ; + goto erase_err; + } + + addr += mtd->erasesize; + len -= mtd->erasesize; + } + } + +spi_nor_unlock_and_unprep (nor,SPI_NOR_OPS_ERASE ); + + instr->state =MTD_ERASE_DONE ; +mtd_erase_callback (instr); + +return ret; + +erase_err: +spi_nor_unlock_and_unprep (nor,SPI_NOR_OPS_ERASE ); + instr->state =MTD_ERASE_FAILED ; +return ret; +} + +static int spi_nor_lock (struct mtd_info *mtd,loff_t ofs,uint64_t len) +{ +struct spi_nor *nor =mtd_to_spi_nor (mtd); +uint32_t offset = ofs; +uint8_t status_old, status_new; +int ret =0 ; + + ret =spi_nor_lock_and_prep (nor,SPI_NOR_OPS_LOCK ); +if (ret) +return ret; + +/* Wait until finished previous command */ + ret =wait_till_ready (nor); +if (ret) + goto err; + + status_old =read_sr (nor); + +if (offset< mtd->size - (mtd->size /2 )) + status_new = status_old |SR_BP2 |SR_BP1 |SR_BP0 ; +else if (offset< mtd->size - (mtd->size /4 )) + status_new = (status_old& ~SR_BP0 ) |SR_BP2 |SR_BP1 ; +else if (offset< mtd->size - (mtd->size /8 )) + status_new = (status_old& ~SR_BP1 ) |SR_BP2 |SR_BP0 ; +else if (offset< mtd->size - (mtd->size /16 )) + status_new = (status_old& ~(SR_BP0 |SR_BP1 )) |SR_BP2 ; +else if (offset< mtd->size - (mtd->size /32 )) + status_new = (status_old& ~SR_BP2 ) |SR_BP1 |SR_BP0 ; +else if (offset< mtd->size - (mtd->size /64 )) + status_new = (status_old& ~(SR_BP2 |SR_BP0 )) |SR_BP1 ; +else + status_new = (status_old& ~(SR_BP2 |SR_BP1 )) |SR_BP0 ; + +/* Only modify protection if it will not unlock other areas */ +if ((status_new& (SR_BP2 |SR_BP1 |SR_BP0 ))> + (status_old& (SR_BP2 |SR_BP1 |SR_BP0 ))) { +write_enable (nor); + ret =write_sr (nor, status_new); +if (ret) + goto err; + } + +err: +spi_nor_unlock_and_unprep (nor,SPI_NOR_OPS_LOCK ); +return ret; +} + +static int spi_nor_unlock (struct mtd_info *mtd,loff_t ofs,uint64_t len) +{ +struct spi_nor *nor =mtd_to_spi_nor (mtd); +uint32_t offset = ofs; +uint8_t status_old, status_new; +int ret =0 ; + + ret =spi_nor_lock_and_prep (nor,SPI_NOR_OPS_UNLOCK ); +if (ret) +return ret; + +/* Wait until finished previous command */ + ret =wait_till_ready (nor); +if (ret) + goto err; + + status_old =read_sr (nor); + +if (offset+len> mtd->size - (mtd->size /64 )) + status_new = status_old& ~(SR_BP2 |SR_BP1 |SR_BP0 ); +else if (offset+len> mtd->size - (mtd->size /32 )) + status_new = (status_old& ~(SR_BP2 |SR_BP1 )) |SR_BP0 ; +else if (offset+len> mtd->size - (mtd->size /16 )) + status_new = (status_old& ~(SR_BP2 |SR_BP0 )) |SR_BP1 ; +else if (offset+len> mtd->size - (mtd->size /8 )) + status_new = (status_old& ~SR_BP2 ) |SR_BP1 |SR_BP0 ; +else if (offset+len> mtd->size - (mtd->size /4 )) + status_new = (status_old& ~(SR_BP0 |SR_BP1 )) |SR_BP2 ; +else if (offset+len> mtd->size - (mtd->size /2 )) + status_new = (status_old& ~SR_BP1 ) |SR_BP2 |SR_BP0 ; +else + status_new = (status_old& ~SR_BP0 ) |SR_BP2 |SR_BP1 ; + +/* Only modify protection if it will not lock other areas */ +if ((status_new& (SR_BP2 |SR_BP1 |SR_BP0 ))< + (status_old& (SR_BP2 |SR_BP1 |SR_BP0 ))) { +write_enable (nor); + ret =write_sr (nor, status_new); +if (ret) + goto err; + } + +err: +spi_nor_unlock_and_unprep (nor,SPI_NOR_OPS_UNLOCK ); +return ret; +} + +struct flash_info { +/* JEDEC id zero means "no ID" (most older chips); otherwise it has +* a high byte of zero plus three data bytes: the manufacturer id, +* then a two byte device id. +*/ +u32 jedec_id; +u16 ext_id; + +/* The size listed here is what works with OPCODE_SE, which isn't +* necessarily called a "sector" by the vendor. +*/ +unsigned sector_size; +u16 n_sectors; + +u16 page_size; +u16 addr_width; + +u16 flags; +#define SECT_4K 0x01/* OPCODE_BE_4K works uniformly */ +#define SPI_NOR_NO_ERASE 0x02/* No erase command needed */ +#define SST_WRITE 0x04/* use SST byte programming */ +#define SPI_NOR_NO_FR 0x08/* Can't do fastread */ +#define SECT_4K_PMC 0x10/* OPCODE_BE_4K_PMC works uniformly */ +#define SPI_NOR_QUAD_READ 0x20/* Flash supports Quad Read */ +}; + +#define INFO (_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ + ((kernel_ulong_t)&(struct flash_info) { \ + .jedec_id = (_jedec_id), \ + .ext_id = (_ext_id), \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = 256, \ + .flags = (_flags), \ + }) + +#define CAT25_INFO (_sector_size, _n_sectors, _page_size, _addr_width, _flags) \ + ((kernel_ulong_t)&(struct flash_info) { \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = (_page_size), \ + .addr_width = (_addr_width), \ + .flags = (_flags), \ + }) + +/* NOTE: double check command sets and memory organization when you add +* more nor chips. This current list focusses on newer chips, which +* have been converging on command sets which including JEDEC ID. +*/ +const struct spi_device_id spi_nor_ids[] = { +/* Atmel -- some are (confusingly) marketed as "DataFlash" */ + {"at25fs010" ,INFO (0x1f6601 ,0 ,32 *1024 ,4 ,SECT_4K ) }, + {"at25fs040" ,INFO (0x1f6604 ,0 ,64 *1024 ,8 ,SECT_4K ) }, + + {"at25df041a" ,INFO (0x1f4401 ,0 ,64 *1024 ,8 ,SECT_4K ) }, + {"at25df321a" ,INFO (0x1f4701 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"at25df641" ,INFO (0x1f4800 ,0 ,64 *1024 ,128 ,SECT_4K ) }, + + {"at26f004" ,INFO (0x1f0400 ,0 ,64 *1024 ,8 ,SECT_4K ) }, + {"at26df081a" ,INFO (0x1f4501 ,0 ,64 *1024 ,16 ,SECT_4K ) }, + {"at26df161a" ,INFO (0x1f4601 ,0 ,64 *1024 ,32 ,SECT_4K ) }, + {"at26df321" ,INFO (0x1f4700 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + + {"at45db081d" ,INFO (0x1f2500 ,0 ,64 *1024 ,16 ,SECT_4K ) }, + +/* EON -- en25xxx */ + {"en25f32" ,INFO (0x1c3116 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"en25p32" ,INFO (0x1c2016 ,0 ,64 *1024 ,64 ,0 ) }, + {"en25q32b" ,INFO (0x1c3016 ,0 ,64 *1024 ,64 ,0 ) }, + {"en25p64" ,INFO (0x1c2017 ,0 ,64 *1024 ,128 ,0 ) }, + {"en25q64" ,INFO (0x1c3017 ,0 ,64 *1024 ,128 ,SECT_4K ) }, + {"en25qh256" ,INFO (0x1c7019 ,0 ,64 *1024 ,512 ,0 ) }, + +/* ESMT */ + {"f25l32pa" ,INFO (0x8c2016 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + +/* Everspin */ + {"mr25h256" ,CAT25_INFO (32 *1024 ,1 ,256 ,2 ,SPI_NOR_NO_ERASE |SPI_NOR_NO_FR ) }, + {"mr25h10" ,CAT25_INFO (128 *1024 ,1 ,256 ,3 ,SPI_NOR_NO_ERASE |SPI_NOR_NO_FR ) }, + +/* GigaDevice */ + {"gd25q32" ,INFO (0xc84016 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"gd25q64" ,INFO (0xc84017 ,0 ,64 *1024 ,128 ,SECT_4K ) }, + +/* Intel/Numonyx -- xxxs33b */ + {"160s33b" ,INFO (0x898911 ,0 ,64 *1024 ,32 ,0 ) }, + {"320s33b" ,INFO (0x898912 ,0 ,64 *1024 ,64 ,0 ) }, + {"640s33b" ,INFO (0x898913 ,0 ,64 *1024 ,128 ,0 ) }, + +/* Macronix */ + {"mx25l2005a" ,INFO (0xc22012 ,0 ,64 *1024 ,4 ,SECT_4K ) }, + {"mx25l4005a" ,INFO (0xc22013 ,0 ,64 *1024 ,8 ,SECT_4K ) }, + {"mx25l8005" ,INFO (0xc22014 ,0 ,64 *1024 ,16 ,0 ) }, + {"mx25l1606e" ,INFO (0xc22015 ,0 ,64 *1024 ,32 ,SECT_4K ) }, + {"mx25l3205d" ,INFO (0xc22016 ,0 ,64 *1024 ,64 ,0 ) }, + {"mx25l3255e" ,INFO (0xc29e16 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"mx25l6405d" ,INFO (0xc22017 ,0 ,64 *1024 ,128 ,0 ) }, + {"mx25l12805d" ,INFO (0xc22018 ,0 ,64 *1024 ,256 ,0 ) }, + {"mx25l12855e" ,INFO (0xc22618 ,0 ,64 *1024 ,256 ,0 ) }, + {"mx25l25635e" ,INFO (0xc22019 ,0 ,64 *1024 ,512 ,0 ) }, + {"mx25l25655e" ,INFO (0xc22619 ,0 ,64 *1024 ,512 ,0 ) }, + {"mx66l51235l" ,INFO (0xc2201a ,0 ,64 *1024 ,1024 ,SPI_NOR_QUAD_READ ) }, + +/* Micron */ + {"n25q064" ,INFO (0x20ba17 ,0 ,64 *1024 ,128 ,0 ) }, + {"n25q128a11" ,INFO (0x20bb18 ,0 ,64 *1024 ,256 ,0 ) }, + {"n25q128a13" ,INFO (0x20ba18 ,0 ,64 *1024 ,256 ,0 ) }, + {"n25q256a" ,INFO (0x20ba19 ,0 ,64 *1024 ,512 ,SECT_4K ) }, + {"n25q512a" ,INFO (0x20bb20 ,0 ,64 *1024 ,1024 ,SECT_4K ) }, + +/* PMC */ + {"pm25lv512" ,INFO (0 ,0 ,32 *1024 ,2 ,SECT_4K_PMC ) }, + {"pm25lv010" ,INFO (0 ,0 ,32 *1024 ,4 ,SECT_4K_PMC ) }, + {"pm25lq032" ,INFO (0x7f9d46 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + +/* Spansion -- single (large) sector size only, at least +* for the chips listed here (without boot sectors). +*/ + {"s25sl032p" ,INFO (0x010215 ,0x4d00 ,64 *1024 ,64 ,0 ) }, + {"s25sl064p" ,INFO (0x010216 ,0x4d00 ,64 *1024 ,128 ,0 ) }, + {"s25fl256s0" ,INFO (0x010219 ,0x4d00 ,256 *1024 ,128 ,0 ) }, + {"s25fl256s1" ,INFO (0x010219 ,0x4d01 ,64 *1024 ,512 ,SPI_NOR_QUAD_READ ) }, + {"s25fl512s" ,INFO (0x010220 ,0x4d00 ,256 *1024 ,256 ,0 ) }, + {"s70fl01gs" ,INFO (0x010221 ,0x4d00 ,256 *1024 ,256 ,0 ) }, + {"s25sl12800" ,INFO (0x012018 ,0x0300 ,256 *1024 ,64 ,0 ) }, + {"s25sl12801" ,INFO (0x012018 ,0x0301 ,64 *1024 ,256 ,0 ) }, + {"s25fl129p0" ,INFO (0x012018 ,0x4d00 ,256 *1024 ,64 ,0 ) }, + {"s25fl129p1" ,INFO (0x012018 ,0x4d01 ,64 *1024 ,256 ,0 ) }, + {"s25sl004a" ,INFO (0x010212 ,0 ,64 *1024 ,8 ,0 ) }, + {"s25sl008a" ,INFO (0x010213 ,0 ,64 *1024 ,16 ,0 ) }, + {"s25sl016a" ,INFO (0x010214 ,0 ,64 *1024 ,32 ,0 ) }, + {"s25sl032a" ,INFO (0x010215 ,0 ,64 *1024 ,64 ,0 ) }, + {"s25sl064a" ,INFO (0x010216 ,0 ,64 *1024 ,128 ,0 ) }, + {"s25fl016k" ,INFO (0xef4015 ,0 ,64 *1024 ,32 ,SECT_4K ) }, + {"s25fl064k" ,INFO (0xef4017 ,0 ,64 *1024 ,128 ,SECT_4K ) }, + +/* SST -- large erase sizes are "overlays", "sectors" are 4K */ + {"sst25vf040b" ,INFO (0xbf258d ,0 ,64 *1024 ,8 ,SECT_4K |SST_WRITE ) }, + {"sst25vf080b" ,INFO (0xbf258e ,0 ,64 *1024 ,16 ,SECT_4K |SST_WRITE ) }, + {"sst25vf016b" ,INFO (0xbf2541 ,0 ,64 *1024 ,32 ,SECT_4K |SST_WRITE ) }, + {"sst25vf032b" ,INFO (0xbf254a ,0 ,64 *1024 ,64 ,SECT_4K |SST_WRITE ) }, + {"sst25vf064c" ,INFO (0xbf254b ,0 ,64 *1024 ,128 ,SECT_4K ) }, + {"sst25wf512" ,INFO (0xbf2501 ,0 ,64 *1024 ,1 ,SECT_4K |SST_WRITE ) }, + {"sst25wf010" ,INFO (0xbf2502 ,0 ,64 *1024 ,2 ,SECT_4K |SST_WRITE ) }, + {"sst25wf020" ,INFO (0xbf2503 ,0 ,64 *1024 ,4 ,SECT_4K |SST_WRITE ) }, + {"sst25wf040" ,INFO (0xbf2504 ,0 ,64 *1024 ,8 ,SECT_4K |SST_WRITE ) }, + +/* ST Microelectronics -- newer production may have feature updates */ + {"m25p05" ,INFO (0x202010 ,0 ,32 *1024 ,2 ,0 ) }, + {"m25p10" ,INFO (0x202011 ,0 ,32 *1024 ,4 ,0 ) }, + {"m25p20" ,INFO (0x202012 ,0 ,64 *1024 ,4 ,0 ) }, + {"m25p40" ,INFO (0x202013 ,0 ,64 *1024 ,8 ,0 ) }, + {"m25p80" ,INFO (0x202014 ,0 ,64 *1024 ,16 ,0 ) }, + {"m25p16" ,INFO (0x202015 ,0 ,64 *1024 ,32 ,0 ) }, + {"m25p32" ,INFO (0x202016 ,0 ,64 *1024 ,64 ,0 ) }, + {"m25p64" ,INFO (0x202017 ,0 ,64 *1024 ,128 ,0 ) }, + {"m25p128" ,INFO (0x202018 ,0 ,256 *1024 ,64 ,0 ) }, + {"n25q032" ,INFO (0x20ba16 ,0 ,64 *1024 ,64 ,0 ) }, + + {"m25p05-nonjedec" ,INFO (0 ,0 ,32 *1024 ,2 ,0 ) }, + {"m25p10-nonjedec" ,INFO (0 ,0 ,32 *1024 ,4 ,0 ) }, + {"m25p20-nonjedec" ,INFO (0 ,0 ,64 *1024 ,4 ,0 ) }, + {"m25p40-nonjedec" ,INFO (0 ,0 ,64 *1024 ,8 ,0 ) }, + {"m25p80-nonjedec" ,INFO (0 ,0 ,64 *1024 ,16 ,0 ) }, + {"m25p16-nonjedec" ,INFO (0 ,0 ,64 *1024 ,32 ,0 ) }, + {"m25p32-nonjedec" ,INFO (0 ,0 ,64 *1024 ,64 ,0 ) }, + {"m25p64-nonjedec" ,INFO (0 ,0 ,64 *1024 ,128 ,0 ) }, + {"m25p128-nonjedec" ,INFO (0 ,0 ,256 *1024 ,64 ,0 ) }, + + {"m45pe10" ,INFO (0x204011 ,0 ,64 *1024 ,2 ,0 ) }, + {"m45pe80" ,INFO (0x204014 ,0 ,64 *1024 ,16 ,0 ) }, + {"m45pe16" ,INFO (0x204015 ,0 ,64 *1024 ,32 ,0 ) }, + + {"m25pe20" ,INFO (0x208012 ,0 ,64 *1024 ,4 ,0 ) }, + {"m25pe80" ,INFO (0x208014 ,0 ,64 *1024 ,16 ,0 ) }, + {"m25pe16" ,INFO (0x208015 ,0 ,64 *1024 ,32 ,SECT_4K ) }, + + {"m25px16" ,INFO (0x207115 ,0 ,64 *1024 ,32 ,SECT_4K ) }, + {"m25px32" ,INFO (0x207116 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"m25px32-s0" ,INFO (0x207316 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"m25px32-s1" ,INFO (0x206316 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"m25px64" ,INFO (0x207117 ,0 ,64 *1024 ,128 ,0 ) }, + +/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ + {"w25x10" ,INFO (0xef3011 ,0 ,64 *1024 ,2 ,SECT_4K ) }, + {"w25x20" ,INFO (0xef3012 ,0 ,64 *1024 ,4 ,SECT_4K ) }, + {"w25x40" ,INFO (0xef3013 ,0 ,64 *1024 ,8 ,SECT_4K ) }, + {"w25x80" ,INFO (0xef3014 ,0 ,64 *1024 ,16 ,SECT_4K ) }, + {"w25x16" ,INFO (0xef3015 ,0 ,64 *1024 ,32 ,SECT_4K ) }, + {"w25x32" ,INFO (0xef3016 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"w25q32" ,INFO (0xef4016 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"w25q32dw" ,INFO (0xef6016 ,0 ,64 *1024 ,64 ,SECT_4K ) }, + {"w25x64" ,INFO (0xef3017 ,0 ,64 *1024 ,128 ,SECT_4K ) }, + {"w25q64" ,INFO (0xef4017 ,0 ,64 *1024 ,128 ,SECT_4K ) }, + {"w25q128" ,INFO (0xef4018 ,0 ,64 *1024 ,256 ,SECT_4K ) }, + {"w25q80" ,INFO (0xef5014 ,0 ,64 *1024 ,16 ,SECT_4K ) }, + {"w25q80bl" ,INFO (0xef4014 ,0 ,64 *1024 ,16 ,SECT_4K ) }, + {"w25q128" ,INFO (0xef4018 ,0 ,64 *1024 ,256 ,SECT_4K ) }, + {"w25q256" ,INFO (0xef4019 ,0 ,64 *1024 ,512 ,SECT_4K ) }, + +/* Catalyst / On Semiconductor -- non-JEDEC */ + {"cat25c11" ,CAT25_INFO (16 ,8 ,16 ,1 ,SPI_NOR_NO_ERASE |SPI_NOR_NO_FR ) }, + {"cat25c03" ,CAT25_INFO (32 ,8 ,16 ,2 ,SPI_NOR_NO_ERASE |SPI_NOR_NO_FR ) }, + {"cat25c09" ,CAT25_INFO (128 ,8 ,32 ,2 ,SPI_NOR_NO_ERASE |SPI_NOR_NO_FR ) }, + {"cat25c17" ,CAT25_INFO (256 ,8 ,32 ,2 ,SPI_NOR_NO_ERASE |SPI_NOR_NO_FR ) }, + {"cat25128" ,CAT25_INFO (2048 ,8 ,64 ,2 ,SPI_NOR_NO_ERASE |SPI_NOR_NO_FR ) }, + { }, +}; + +static const struct spi_device_id *spi_nor_read_id (struct spi_nor *nor) +{ +int tmp; +u8 id[5 ]; +u32 jedec; +u16 ext_jedec; +struct flash_info *info; + + tmp = nor->read_reg (nor,OPCODE_RDID , id,5 ); +if (tmp<0 ) { +dev_dbg (nor->dev," error %d reading JEDEC ID\n" , tmp); +return ERR_PTR (tmp); + } + jedec = id[0 ]; + jedec = jedec<<8 ; + jedec |= id[1 ]; + jedec = jedec<<8 ; + jedec |= id[2 ]; + + ext_jedec = id[3 ]<<8 | id[4 ]; + +for (tmp =0 ; tmp<ARRAY_SIZE (spi_nor_ids) -1 ; tmp++) { + info = (void *)spi_nor_ids[tmp].driver_data; +if (info->jedec_id == jedec) { +if (info->ext_id !=0 && info->ext_id != ext_jedec) +continue ; +return &spi_nor_ids[tmp]; + } + } +pr_err ("unrecognized JEDEC id %06x\n" , jedec); +return ERR_PTR (-ENODEV ); +} + +static const struct spi_device_id *jedec_probe (struct spi_nor *nor) +{ +return nor->read_id (nor); +} + +static int spi_nor_read (struct mtd_info *mtd,loff_t from,size_t len, +size_t *retlen,u_char *buf) +{ +struct spi_nor *nor =mtd_to_spi_nor (mtd); +int ret; + +dev_dbg (nor->dev,"from 0x%08x, len %zd\n" , (u32 )from, len);
drivers/mtd/spi-nor/spi-nor.c line 657
Quoted 10 lines
drivers/mtd/spi-nor/spi-nor.c new file +10
-0+ + ret =spi_nor_lock_and_prep (nor,SPI_NOR_OPS_READ ); +if (ret) +return ret; + +/* Wait till previous write/erase is done. */ + ret =wait_till_ready (nor); +if (ret) + goto read_err; +
Can you shift "wait_till_ready" above spi_nor_lock_and_prep? One usecase for asking for above change is that I am planning to use this _prep api for switching to memory mapped mode for read and once I am switched to mmap mode, read_sr calls in wait_till_ready will not work for me.
Quoted 443 lines
drivers/mtd/spi-nor/spi-nor.c new file +429
-0+ ret = nor->read (nor, from, len, retlen, buf); + +read_err: +spi_nor_unlock_and_unprep (nor,SPI_NOR_OPS_READ ); +return ret; +} + +static int sst_write (struct mtd_info *mtd,loff_t to,size_t len, +size_t *retlen,const u_char *buf) +{ +struct spi_nor *nor =mtd_to_spi_nor (mtd); +size_t actual; +int ret; + +dev_dbg (nor->dev,"to 0x%08x, len %zd\n" , (u32 )to, len); + + ret =spi_nor_lock_and_prep (nor,SPI_NOR_OPS_WRITE ); +if (ret) +return ret; + +/* Wait until finished previous write command. */ + ret =wait_till_ready (nor); +if (ret) + goto time_out; + +write_enable (nor); + + nor->sst_write_second = false; + + actual = to %2 ; +/* Start write from odd address. */ +if (actual) { + nor->program_opcode =OPCODE_BP ; + +/* write one byte. */ + nor->write (nor, to,1 , retlen, buf); + ret =wait_till_ready (nor); +if (ret) + goto time_out; + } + to += actual; + +/* Write out most of the data here. */ +for (; actual< len -1 ; actual +=2 ) { + nor->program_opcode =OPCODE_AAI_WP ; + +/* write two bytes. */ + nor->write (nor, to,2 , retlen, buf + actual); + ret =wait_till_ready (nor); +if (ret) + goto time_out; + to +=2 ; + nor->sst_write_second = true; + } + nor->sst_write_second = false; + +write_disable (nor); + ret =wait_till_ready (nor); +if (ret) + goto time_out; + +/* Write out trailing byte if it exists. */ +if (actual != len) { +write_enable (nor); + + nor->program_opcode =OPCODE_BP ; + nor->write (nor, to,1 , retlen, buf + actual); + + ret =wait_till_ready (nor); +if (ret) + goto time_out; +write_disable (nor); + } +time_out: +spi_nor_unlock_and_unprep (nor,SPI_NOR_OPS_WRITE ); +return ret; +} + +/* +* Write an address range to the nor chip. Data must be written in +* FLASH_PAGESIZE chunks. The address range may be any size provided +* it is within the physical boundaries. +*/ +static int spi_nor_write (struct mtd_info *mtd,loff_t to,size_t len, +size_t *retlen,const u_char *buf) +{ +struct spi_nor *nor =mtd_to_spi_nor (mtd); +u32 page_offset, page_size, i; +int ret; + +dev_dbg (nor->dev,"to 0x%08x, len %zd\n" , (u32 )to, len); + + ret =spi_nor_lock_and_prep (nor,SPI_NOR_OPS_WRITE ); +if (ret) +return ret; + +/* Wait until finished previous write command. */ + ret =wait_till_ready (nor); +if (ret) + goto write_err; + +write_enable (nor); + + page_offset = to& (nor->page_size -1 ); + +/* do all the bytes fit onto one page? */ +if (page_offset + len<= nor->page_size) { + nor->write (nor, to, len, retlen, buf); + }else { +/* the size of data remaining on the first page */ + page_size = nor->page_size - page_offset; + nor->write (nor, to, page_size, retlen, buf); + +/* write everything in nor->page_size chunks */ +for (i = page_size; i< len; i += page_size) { + page_size = len - i; +if (page_size> nor->page_size) + page_size = nor->page_size; + +wait_till_ready (nor); +write_enable (nor); + + nor->write (nor, to + i, page_size, retlen, buf + i); + } + } + +write_err: +spi_nor_unlock_and_unprep (nor,SPI_NOR_OPS_WRITE ); +return 0 ; +} + +static int macronix_quad_enable (struct spi_nor *nor) +{ +int ret, val; + + val =read_sr (nor); +write_enable (nor); + + nor->cmd_buf[0 ] = val |SR_QUAD_EN_MX ; + nor->write_reg (nor,OPCODE_WRSR , nor->cmd_buf,1 ,0 ); + +if (wait_till_ready (nor)) +return 1 ; + + ret =read_sr (nor); +if (!(ret>0 && (ret&SR_QUAD_EN_MX ))) { +dev_err (nor->dev,"Macronix Quad bit not set\n" ); +return -EINVAL ; + } + +return 0 ; +} + +static int spansion_quad_enable (struct spi_nor *nor) +{ +int ret; +int quad_en =CR_QUAD_EN_SPAN <<8 ; + +write_enable (nor); + + ret =write_sr_cr (nor, quad_en); +if (ret<0 ) { +dev_err (nor->dev, +"error while writing configuration register\n" ); +return -EINVAL ; + } + +/* read back and check it */ + ret =read_cr (nor); +if (!(ret>0 && (ret&CR_QUAD_EN_SPAN ))) { +dev_err (nor->dev,"Spansion Quad bit not set\n" ); +return -EINVAL ; + } + +return 0 ; +} + +static int set_quad_mode (struct spi_nor *nor,u32 jedec_id) +{ +int status; + +switch (JEDEC_MFR (jedec_id)) { +case CFI_MFR_MACRONIX : + status =macronix_quad_enable (nor); +if (status) { +dev_err (nor->dev,"Macronix quad-read not enabled\n" ); +return -EINVAL ; + } +return status; +default : + status =spansion_quad_enable (nor); +if (status) { +dev_err (nor->dev,"Spansion quad-read not enabled\n" ); +return -EINVAL ; + } +return status; + } +} + +static int spi_nor_check (struct spi_nor *nor) +{ +if (!nor->dev || !nor->read || !nor->write || + !nor->read_reg || !nor->write_reg || !nor->erase) { +pr_err ("spi-nor: please fill all the necessary fields!\n" ); +return -EINVAL ; + } + +if (!nor->read_id) + nor->read_id = spi_nor_read_id; +if (!nor->wait_till_ready) + nor->wait_till_ready = spi_nor_wait_till_ready; + +return 0 ; +} + +int spi_nor_scan (struct spi_nor *nor,const struct spi_device_id *id, +enum read_mode mode) +{ +struct flash_info *info; +struct flash_platform_data *data; +struct device *dev = nor->dev; +struct mtd_info *mtd = nor->mtd; +struct device_node *np = dev->of_node; +int ret; +int i; + + ret =spi_nor_check (nor); +if (ret) +return ret; + +/* Platform data helps sort out which chip type we have, as +* well as how this board partitions it. If we don't have +* a chip ID, try the JEDEC id commands; they'll work for most +* newer chips, even if we don't recognize the particular chip. +*/ + data =dev_get_platdata (dev); +if (data&& data->type) { +const struct spi_device_id *plat_id; + +for (i =0 ; i<ARRAY_SIZE (spi_nor_ids) -1 ; i++) { + plat_id =&spi_nor_ids[i]; +if (strcmp (data->type, plat_id->name)) +continue ; +break ; + } + +if (i<ARRAY_SIZE (spi_nor_ids) -1 ) + id = plat_id; +else +dev_warn (dev,"unrecognized id %s\n" , data->type); + } + + info = (void *)id->driver_data; + +if (info->jedec_id) { +const struct spi_device_id *jid; + + jid =jedec_probe (nor); +if (IS_ERR (jid)) { +return PTR_ERR (jid); + }else if (jid != id) { +/* +* JEDEC knows better, so overwrite platform ID. We +* can't trust partitions any longer, but we'll let +* mtd apply them anyway, since some partitions may be +* marked read-only, and we don't want to lose that +* information, even if it's not 100% accurate. +*/ +dev_warn (dev,"found %s, expected %s\n" , + jid->name, id->name); + id = jid; + info = (void *)jid->driver_data; + } + } + +mutex_init (&nor->lock); + +/* +* Atmel, SST and Intel/Numonyx serial nor tend to power +* up with the software protection bits set +*/ + +if (JEDEC_MFR (info->jedec_id) ==CFI_MFR_ATMEL || +JEDEC_MFR (info->jedec_id) ==CFI_MFR_INTEL || +JEDEC_MFR (info->jedec_id) ==CFI_MFR_SST ) { +write_enable (nor); +write_sr (nor,0 ); + } + +if (data&& data->name) + mtd->name = data->name; +else + mtd->name =dev_name (dev); + + mtd->type =MTD_NORFLASH ; + mtd->writesize =1 ; + mtd->flags =MTD_CAP_NORFLASH ; + mtd->size = info->sector_size * info->n_sectors; + mtd->_erase = spi_nor_erase; + mtd->_read = spi_nor_read; + +/* nor protection support for STmicro chips */ +if (JEDEC_MFR (info->jedec_id) ==CFI_MFR_ST ) { + mtd->_lock = spi_nor_lock; + mtd->_unlock = spi_nor_unlock; + } + +/* sst nor chips use AAI word program */ +if (info->flags&SST_WRITE ) + mtd->_write = sst_write; +else + mtd->_write = spi_nor_write; + +/* prefer "small sector" erase if possible */ +if (info->flags&SECT_4K ) { + nor->erase_opcode =OPCODE_BE_4K ; + mtd->erasesize =4096 ; + }else if (info->flags&SECT_4K_PMC ) { + nor->erase_opcode =OPCODE_BE_4K_PMC ; + mtd->erasesize =4096 ; + }else { + nor->erase_opcode =OPCODE_SE ; + mtd->erasesize = info->sector_size; + } + +if (info->flags&SPI_NOR_NO_ERASE ) + mtd->flags |=MTD_NO_ERASE ; + + mtd->dev.parent = dev; + nor->page_size = info->page_size; + mtd->writebufsize = nor->page_size; + +if (np) { +/* If we were instantiated by DT, use it */ +if (of_property_read_bool (np,"m25p,fast-read" )) + nor->flash_read =SPI_NOR_FAST ; + }else { +/* If we weren't instantiated by DT, default to fast-read */ + nor->flash_read =SPI_NOR_FAST ; + } + +/* Some devices cannot do fast-read, no matter what DT tells us */ +if (info->flags&SPI_NOR_NO_FR ) + nor->flash_read =SPI_NOR_NORMAL ; + +/* Quad-read mode takes precedence over fast/normal */ +if (mode ==SPI_NOR_QUAD && info->flags&SPI_NOR_QUAD_READ ) { + ret =set_quad_mode (nor, info->jedec_id); +if (ret) { +dev_err (dev,"quad mode not supported\n" ); +return ret; + } + nor->flash_read =SPI_NOR_QUAD ; + } + +/* Default commands */ +switch (nor->flash_read) { +case SPI_NOR_QUAD : + nor->read_opcode =OPCODE_QUAD_READ ; +break ; +case SPI_NOR_FAST : + nor->read_opcode =OPCODE_FAST_READ ; +break ; +case SPI_NOR_NORMAL : + nor->read_opcode =OPCODE_NORM_READ ; +break ; +default : +dev_err (dev,"No Read opcode defined\n" ); +return -EINVAL ; + } + + nor->program_opcode =OPCODE_PP ; + +if (info->addr_width) + nor->addr_width = info->addr_width; +else if (mtd->size>0x1000000 ) { +/* enable 4-byte addressing if the device exceeds 16MiB */ + nor->addr_width =4 ; +if (JEDEC_MFR (info->jedec_id) ==CFI_MFR_AMD ) { +/* Dedicated 4-byte command set */ +switch (nor->flash_read) { +case SPI_NOR_QUAD : + nor->read_opcode =OPCODE_QUAD_READ ; +break ; +case SPI_NOR_FAST : + nor->read_opcode =OPCODE_FAST_READ_4B ; +break ; +case SPI_NOR_NORMAL : + nor->read_opcode =OPCODE_NORM_READ_4B ; +break ; + } + nor->program_opcode =OPCODE_PP_4B ; +/* No small sector erase for 4-byte command set */ + nor->erase_opcode =OPCODE_SE_4B ; + mtd->erasesize = info->sector_size; + }else +set_4byte (nor, info->jedec_id,1 ); + }else { + nor->addr_width =3 ; + } + + nor->read_dummy =spi_nor_read_dummy_cycles (nor); + +dev_info (dev,"%s (%lld Kbytes)\n" , id->name, + (long long )mtd->size>>10 ); + +dev_dbg (dev,"mtd .name = %s, .size = 0x%llx (%lldMiB) " +".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n" , + mtd->name, + (long long )mtd->size, (long long )(mtd->size>>20 ), + mtd->erasesize, mtd->erasesize /1024 , + mtd->numeraseregions); + +if (mtd->numeraseregions) +for (i =0 ; i< mtd->numeraseregions; i++) +dev_dbg (dev, +"mtd.eraseregions[%d] = { .offset = 0x%llx, " +".erasesize = 0x%.8x (%uKiB), " +".numblocks = %d }\n" , + i, (long long )mtd->eraseregions[i].offset, + mtd->eraseregions[i].erasesize, + mtd->eraseregions[i].erasesize /1024 , + mtd->eraseregions[i].numblocks); +return 0 ; +} + +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR ("Freescale Semiconductor Inc." ); +MODULE_DESCRIPTION ("framework for SPI NOR nor" );include/linux/mtd/spi-nor.h +5
-0@@ -158,4 +158,9 @@ struct spi_nor { void *priv; }; + +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[]; +#endif
PATCH v3 3/7 mtd: spi-nor: add the framework for SPI NOR
Quoted 15 lines · Sourav Poddar
Quoted 15 lines
drivers/mtd/spi-nor/spi-nor.c new file +15
-0+static int spi_nor_read (struct mtd_info *mtd,loff_t from,size_t len, +size_t *retlen,u_char *buf) +{ +struct spi_nor *nor =mtd_to_spi_nor (mtd); +int ret; + +dev_dbg (nor->dev,"from 0x%08x, len %zd\n" , (u32 )from, len); + + ret =spi_nor_lock_and_prep (nor,SPI_NOR_OPS_READ ); +if (ret) +return ret; + +/* Wait till previous write/erase is done. */ + ret =wait_till_ready (nor); +if (ret)
Quoted 9 lines
drivers/mtd/spi-nor/spi-nor.c line 657
Quoted 2 lines
drivers/mtd/spi-nor/spi-nor.c new file +2
-0+ goto read_err; +Can you shift "
wait_till_ready" abovespi_nor_lock_and_prep? One usecase for asking for above change is that I am planning to use this_prepapi for switching to memory mapped mode for read and once I am switched to mmap mode,read_srcalls inwait_till_readywill not work for me.
you can implement your own wait_till_ready here.
Only we have grabbed the lock, then we can do the transactions with the NOR.
We can not call the wait_till_ready before we grab the lock, it is wrong.
If you really can not implement your own wait_till_ready, the final solution is removing the wait_till_ready in this function, and add the wait_till_ready in the nor->read() hook.
thanks
Huang Shijie
PATCH v3 3/7 mtd: spi-nor: add the framework for SPI NOR
Quoted 24 lines · Huang Shijie
Quoted 14 lines · Sourav Poddar
Quoted 14 lines
drivers/mtd/spi-nor/spi-nor.c new file +14
-0+static int spi_nor_read (struct mtd_info *mtd,loff_t from,size_t len, +size_t *retlen,u_char *buf) +{ +struct spi_nor *nor =mtd_to_spi_nor (mtd); +int ret; + +dev_dbg (nor->dev,"from 0x%08x, len %zd\n" , (u32 )from, len); + + ret =spi_nor_lock_and_prep (nor,SPI_NOR_OPS_READ ); +if (ret) +return ret; + +/* Wait till previous write/erase is done. */ + ret =wait_till_ready (nor);Quoted 9 lines
drivers/mtd/spi-nor/spi-nor.c line 657
Quoted 3 lines
drivers/mtd/spi-nor/spi-nor.c new file +3
-0+if (ret) + goto read_err; +Can you shift "
wait_till_ready" abovespi_nor_lock_and_prep? One usecase for asking for above change is that I am planning to use this_prepapi for switching to memory mapped mode for read and once I am switched to mmap mode,read_srcalls inwait_till_readywill not work for me.
Quoted 1 line
you can implement your own
wait_till_readyhere.
I think no point doing this, since it does the same function for me.
Quoted 9 lines
Only we have grabbed the lock, then we can do the transactions with the NOR.
We can not call the
wait_till_readybefore we grab the lock, it is wrong.If you really can not implement your own
wait_till_ready, the final solution is removing thewait_till_readyin this function, and add thewait_till_readyin thenor->read()hook.
Yes, this can be done. So, that if you want to do memcpy do it before this condition is hit.
Quoted 4 lines
thanks
Huang Shijie
PATCH v3 3/7 mtd: spi-nor: add the framework for SPI NOR
Quoted 32 lines · Sourav Poddar
Quoted 24 lines · Huang Shijie
Quoted 14 lines · Sourav Poddar
Quoted 14 lines
drivers/mtd/spi-nor/spi-nor.c new file +14
-0+static int spi_nor_read (struct mtd_info *mtd,loff_t from,size_t len, +size_t *retlen,u_char *buf) +{ +struct spi_nor *nor =mtd_to_spi_nor (mtd); +int ret; + +dev_dbg (nor->dev,"from 0x%08x, len %zd\n" , (u32 )from, len); + + ret =spi_nor_lock_and_prep (nor,SPI_NOR_OPS_READ ); +if (ret) +return ret; + +/* Wait till previous write/erase is done. */ + ret =wait_till_ready (nor);Quoted 9 lines
drivers/mtd/spi-nor/spi-nor.c line 657
Quoted 3 lines
drivers/mtd/spi-nor/spi-nor.c new file +3
-0+if (ret) + goto read_err; +Can you shift "
wait_till_ready" abovespi_nor_lock_and_prep? One usecase for asking for above change is that I am planning to use this_prepapi for switching to memory mapped mode for read and once I am switched to mmap mode,read_srcalls inwait_till_readywill not work for me.Quoted 1 line
you can implement your own
wait_till_readyhere.I think no point doing this, since it does the same function for me.
Quoted 5 lines
Only we have grabbed the lock, then we can do the transactions with the NOR.
We can not call the
wait_till_readybefore we grab the lock, it is wrong.
Quoted 7 lines
Quoted 4 lines
If you really can not implement your own
wait_till_ready, the final solution is removing thewait_till_readyin this function, and add thewait_till_readyin thenor->read()hook.Yes, this can be done. So, that if you want to do memcpy do it before this condition is hit.
ok.
I can fix it in the next version.
thanks
Huang Shijie
PATCH v3 3/7 mtd: spi-nor: add the framework for SPI NOR
In reply to Huang ShijieQuoted 33 lines · Huang Shijie
This 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 chip
Quoted 2 lines
New APIs:
spi_nor_scan: used to scan a spi-nor flash.
Document every single one function with a proper kernel-doc style annotations please.
Best regards,
Marek Vasut
PATCH v3 4/7 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 | 1271 ++++-------------------------------------- 2 files changed, 95 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 +94 -1177
1,379 lines not on this page · raw message
Signature · 1 line
1.7.2.rc3
PATCH v3 5/7 mtd: spi-nor: add a helper to find the spi_device_id
In reply to Huang ShijieAdd the spi_nor_match_id() to find the proper spi_device_id in the spi_nor_ids table.
--- drivers/mtd/spi-nor/spi-nor.c | 12 ++++++++++++ include/linux/mtd/spi-nor.h | 1 + 2 files changed, 13 insertions(+), 0 deletions(-)
drivers/mtd/spi-nor/spi-nor.c +12 -0
@@ -1081,6 +1081,18 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,return 0 ; } +const struct spi_device_id *spi_nor_match_id (char *name) +{ +const struct spi_device_id *id = spi_nor_ids; + +while (id->name[0 ]) { +if (!strcmp (name, id->name)) +return id; + id++; + } +return NULL ; +} +MODULE_LICENSE ("GPL" );MODULE_AUTHOR ("Freescale Semiconductor Inc." );MODULE_DESCRIPTION ("framework for SPI NOR nor" );
include/linux/mtd/spi-nor.h +1 -0
@@ -162,5 +162,6 @@ struct spi_nor {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[]; +const struct spi_device_id *spi_nor_match_id (char *name);#endif
Signature · 1 line
1.7.2.rc3
PATCH v3 6/7 Documentation: add the binding file for Quadspi driver
In reply to Huang ShijieThis patch adds the binding file for Freescale Quadspi driver.
--- .../devicetree/bindings/mtd/fsl-quadspi.txt | 31 ++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/mtd/fsl-quadspi.txt
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +31 -0
@@ -0,0 +1,31 @@ +* Freescale Quad Serial Peripheral Interface(QuadSPI) + +Required properties: +- compatible : Should be "fsl,vf610-qspi" +- reg : Offset and length of the register set for the device +- interrupts : Should contain the interrupt for the device +- clocks : The clocks needed by the QuadSPI controller +- clock-names : the name of the clocks +- fsl,nor-num : Contains the number of SPI NOR chips connected to + the controller. +- fsl,nor-size : the size of each SPI NOR. +- fsl,max-frequency : the frequency at which the SPI NOR works. + +Example: + +qspi0: quadspi at 40044000 { + compatible = "fsl,vf610-qspi"; + reg = <0x40044000 0x1000>; + interrupts = <0 24 0x04>; + clocks = <&clks VF610_CLK_QSPI0_EN>, + <&clks VF610_CLK_QSPI0>; + clock-names = "qspi_en", "qspi"; + fsl,nor-num = <1>; + fsl,nor-size = <0x1000000>; + fsl,max-frequency = <66000000>; + status = "okay"; + + flash0: s25fl128s at 0 { + .... + }; +};
Signature · 1 line
1.7.2.rc3
PATCH v3 6/7 Documentation: add the binding file for Quadspi driver
Quoted 3 lines · Huang Shijie
This patch adds the binding file for Freescale Quadspi driver.
Signed-off-by Huang Shijie <[email protected]>
I might be blind and/or tired, but I don't see devicetree-discuss in the CC. Next time please CC this ML ( devicetree-discuss AT lists.ozlabs.org ) so the bindings are reviewed by experts .
Best regards,
Marek Vasut
PATCH v3 6/7 Documentation: add the binding file for Quadspi driver
Hello Marek,
Marek Vasut wrote on?2013-12-17:
Quoted 8 lines · Huang Shijie
Quoted 3 lines
This patch adds the binding file for Freescale Quadspi driver.
Signed-off-by Huang Shijie <[email protected]>I might be blind and/or tired, but I don't see devicetree-discuss in the CC. Next time please CC this ML ( devicetree-discuss AT lists.ozlabs.org ) so the bindings are reviewed by experts .
I am sure you talking about the new list at devicetree at vger.kernel.org?
Quoted 3 lines
Best regards,
Marek Vasut
Best Regards,
Thomas
---
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
---
PATCH v3 6/7 Documentation: add the binding file for Quadspi driver
Quoted 6 lines · thomas.langer at lantiq.com
Hello Marek,
Marek Vasut wrote on 2013-12-17:
Quoted 3 lines · Huang Shijie
Quoted 2 lines
This patch adds the binding file for Freescale Quadspi driver.
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
Signed-off-by Huang Shijie <[email protected]>I might be blind and/or tired, but I don't see devicetree-discuss in the CC. Next time please CC this ML ( devicetree-discuss AT lists.ozlabs.org ) so the bindings are reviewed by experts .
I am sure you talking about the new list at devicetree at vger.kernel.org?
Yes, thanks for correcting it.
Best regards,
Marek Vasut
PATCH v3 6/7 Documentation: add the binding file for Quadspi driver
In reply to Huang Shijie[ adding Cc: to devicetree; make sure to keep 'binding' in the
subject line upon re-submission, such that reviewers can tell whether you introduce a new binding, or just use an existing binding and implement it in a dts/dtsi file ]
Quoted 17 lines · Huang Shijie
This patch adds the binding file for Freescale Quadspi driver.
Signed-off-by Huang Shijie <[email protected]>--- .../devicetree/bindings/mtd/fsl-quadspi.txt | 31 ++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/mtd/fsl-quadspi.txtDocumentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +2
-0@@ -0,0 +1,31 @@ +* Freescale Quad Serial Peripheral Interface(QuadSPI) +
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt line 12
Quoted 10 lines
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +10
-0+Required properties: +- compatible : Should be "fsl,vf610-qspi" +- reg : Offset and length of the register set for the device +- interrupts : Should contain the interrupt for the device +- clocks : The clocks needed by the QuadSPI controller +- clock-names : the name of the clocks +- fsl,nor-num : Contains the number of SPI NOR chips connected to + the controller. +- fsl,nor-size : the size of each SPI NOR. +- fsl,max-frequency : the frequency at which the SPI NOR works.
Those "fsl,*" properties somehow feel strange. I comment on details below the example since this should even better show why I feel so.
Quoted 9 lines
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +9
-0+ +Example: + +qspi0: quadspi at 40044000 { + compatible = "fsl,vf610-qspi"; + reg = <0x40044000 0x1000>; + interrupts = <0 24 0x04>; + clocks = <&clks VF610_CLK_QSPI0_EN>, + <&clks VF610_CLK_QSPI0>;
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt line 31
Quoted 10 lines
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +10
-0+ clock-names = "qspi_en", "qspi"; + fsl,nor-num = <1>; + fsl,nor-size = <0x1000000>; + fsl,max-frequency = <66000000>; + status = "okay"; + + flash0: s25fl128s at 0 { + .... + }; +};
The number of chips connected to the controller should reflect in the child nodes of the SPI NOR controller, and need not get specified in redundant ways and with potential for errors when they can get determined at runtime.
The capacity of the flash chip as well as the maximum frequency which the flash chip operates at should be features of the flash chip (in combination with the board), i.e. of the child node and not the controller. SPI slaves already have a documented property for the purpose of limiting transfer rates when they are lower than the controller's i.e. busses capabilities. Can't tell from the top of my head whether there is a property for the maximum frequency which a controller should use across the whole bus. In any case, either the property needs to get moved, or the description should get updated to say "the max frequency at which the controller will send data" or something.
The capacity of the flash chip should be a consequence of either having gathered CFI information (if available) or having identified the chip by its JEDEC ID and looked up its features in an internal database. Users should not need to specify the capacity of the flash chip in the device tree.
If the 'fsl,nor-size' property remains (which I doubt at the moment), you cannot describe "the size of each" chip in one single-cell spec. So the documentation should get extended to reflect multi-chip setups. But I'd rather assume that the property is not needed at all.
You can omit the 'status = "okay"' line since that is the default already in the absence of the keyword. This property is most useful to declare yet not enable by default components in .dtsi files and to do enable them in individual board files if applicable. This aspect need not be shown in the binding example of a QSPI controller.
I'd suggest to use symbolic names for the flags in the last interrupt specifier cell, as you do for clock items.
And while I'm in nitpick mode :) let me say that I dislike the blanking around the colons in the properties discussion, but I'm as well aware that these are "inspired by" the early OF/DT documents. There may be as many expectations about formatting of a document as there are readers/consumers.
virtually yours
Gerhard Sittig
Signature · 3 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office at denx.de
PATCH v3 6/7 Documentation: add the binding file for Quadspi driver
Quoted 36 lines · Gerhard Sittig
Quoted 4 lines
+++
b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txtDocumentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +2
-0@@ -0,0 +1,31 @@ +* Freescale Quad Serial Peripheral Interface(QuadSPI) +Documentation/devicetree/bindings/mtd/fsl-quadspi.txt line 12
Quoted 10 lines
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +10
-0+Required properties: +- compatible : Should be "fsl,vf610-qspi" +- reg : Offset and length of the register set for the device +- interrupts : Should contain the interrupt for the device +- clocks : The clocks needed by the QuadSPI controller +- clock-names : the name of the clocks +- fsl,nor-num : Contains the number of SPI NOR chips connected to + the controller. +- fsl,nor-size : the size of each SPI NOR. +- fsl,max-frequency : the frequency at which the SPI NOR works.Those "fsl,*" properties somehow feel strange. I comment on details below the example since this should even better show why I feel so.
Quoted 17 lines
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +17
-0+ +Example: + +qspi0: quadspi at 40044000 { + compatible = "fsl,vf610-qspi"; + reg = <0x40044000 0x1000>; + interrupts = <0 24 0x04>; + clocks = <&clks VF610_CLK_QSPI0_EN>, + <&clks VF610_CLK_QSPI0>; + clock-names = "qspi_en", "qspi"; + fsl,nor-num = <1>; + fsl,nor-size = <0x1000000>; + fsl,max-frequency = <66000000>; + status = "okay"; + + flash0: s25fl128s at 0 { + ....
Quoted 8 lines
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt line 31
Quoted 2 lines
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +2
-0+ }; +};The number of chips connected to the controller should reflect in the child nodes of the SPI NOR controller, and need not get specified in redundant ways and with potential for errors when they can get determined at runtime.
thanks. I have already removed this property in the next version.
Quoted 4 lines
The capacity of the flash chip as well as the maximum frequency which the flash chip operates at should be features of the flash chip (in combination with the board), i.e. of the child node and
agree.
thanks.
Quoted 9 lines
not the controller. SPI slaves already have a documented property for the purpose of limiting transfer rates when they are lower than the controller's i.e. busses capabilities. Can't tell from the top of my head whether there is a property for the maximum frequency which a controller should use across the whole bus. In any case, either the property needs to get moved, or the description should get updated to say "the max frequency at which the controller will send data" or something.
Quoted 5 lines
The capacity of the flash chip should be a consequence of either having gathered CFI information (if available) or having identified the chip by its JEDEC ID and looked up its features in an internal database. Users should not need to specify the capacity of the flash chip in the device tree.
I will remove it in the next version.
Quoted 15 lines
If the 'fsl,nor-size' property remains (which I doubt at the moment), you cannot describe "the size of each" chip in one single-cell spec. So the documentation should get extended to reflect multi-chip setups. But I'd rather assume that the property is not needed at all.
You can omit the 'status = "okay"' line since that is the default already in the absence of the keyword. This property is most useful to declare yet not enable by default components in .dtsi files and to do enable them in individual board files if applicable. This aspect need not be shown in the binding example of a QSPI controller.
Quoted 2 lines
I'd suggest to use symbolic names for the flags in the last interrupt specifier cell, as you do for clock items.
I will use the symbolic name if it has.
But if it not have a symbolic name, i have to keep it as it is now.
Thanks
Huang Shijie
PATCH v3 6/7 Documentation: add the binding file for Quadspi driver
Quoted 16 lines · Huang Shijie
Quoted 6 lines · Gerhard Sittig
Quoted 6 lines
+++
b/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt[ ... ]Documentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +4
-0+Example: + +qspi0: quadspi at 40044000 { + compatible = "fsl,vf610-qspi";Quoted 8 lines
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt line 30
Quoted 4 lines
Documentation/devicetree/bindings/mtd/fsl-quadspi.txt new file +3
-0+ reg = <0x40044000 0x1000>; + interrupts = <0 24 0x04>; +};[ ... ]
I'd suggest to use symbolic names for the flags in the last interrupt specifier cell, as you do for clock items.
Quoted 2 lines
I will use the symbolic name if it has.
But if it not have a symbolic name, i have to keep it as it is now.
To avoid potential confusion: I meant symbolic names for the _flags_ of the interrupt specifier (i.e. trigger type and polarity). The <dt-bindings/interrupt-controller/irq.h> file has IRQ_TYPE_LEVEL_HIGH with value 4 for you.
virtually yours
Gerhard Sittig
Signature · 3 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office at denx.de
PATCH v3 7/7 mtd: spi-nor: Add Freescale QuadSpi driver
In reply to Huang Shijie(0) What is the Quadspi controller?
The Quadspi(Quad Serial Peripheral Interface) acts as an interface to one single or two external serial flash devices, each with up to 4 bidirectional data lines.
(1) The Quadspi controller is driven by the LUT(Look-up Table) registers. The LUT registers are a look-up-table for sequences of instructions. A valid sequence consists of four LUT registers.
(2) The definition of the LUT register shows below:
---------------------------------------------------
| INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 |
---------------------------------------------------
There are several types of INSTRx, such as:
CMD : the SPI NOR command.
ADDR : the address for the SPI NOR command.
DUMMY : the dummy cycles needed by the SPI NOR command.
....
There are several types of PADx, such as:
PAD1 : use a singe I/O line.
PAD2 : use two I/O lines.
PAD4 : use quad I/O lines.
....
(3) Test this driver with the JFFS2 and UBIFS:
For jffs2:
-------------
#flash_eraseall /dev/mtd0
#mount -t jffs2 /dev/mtdblock0 tmp
#bonnie++ -d tmp -u 0 -s 10 -r 5
For ubifs:
-------------
#flash_eraseall /dev/mtd0
#ubiattach /dev/ubi_ctrl -m 0
#ubimkvol /dev/ubi0 -N test -m
#mount -t ubifs ubi0:test tmp
#bonnie++ -d tmp -u 0 -s 10 -r 5
--- drivers/mtd/spi-nor/Kconfig | 6 + drivers/mtd/spi-nor/Makefile | 1 + drivers/mtd/spi-nor/fsl-quadspi.c | 927 +++++++++++++++++++++++++++++++++++++ 3 files changed, 934 insertions(+), 0 deletions(-) create mode 100644 drivers/mtd/spi-nor/fsl-quadspi.c
drivers/mtd/spi-nor/Kconfig +6 -0
@@ -4,3 +4,9 @@ config MTD_SPI_NOR_BASE help This is the framework for the SPI NOR which can be used by the SPI device drivers and the SPI-NOR device driver. +config SPI_FSL_QUADSPI + tristate "Freescale Quad SPI controller" + depends on ARCH_MXC && MTD_SPI_NOR_BASE + help + This enables support for the Quad SPI controller in master mode. + We only connect the NOR to this controller now.
drivers/mtd/spi-nor/Makefile +1 -0
@@ -1 +1,2 @@ obj-$(CONFIG_MTD_SPI_NOR_BASE) += spi-nor.o +obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
drivers/mtd/spi-nor/fsl-quadspi.c new file +927 -0
927 lines not on this page · raw message
Signature · 1 line
1.7.2.rc3
PATCH v3 7/7 mtd: spi-nor: Add Freescale QuadSpi driver
On Monday, December 16, 2013 at 09:58:50 AM, Huang Shijie wrote:
[...]
drivers/mtd/spi-nor/fsl-quadspi.c line 166
Quoted 6 lines
drivers/mtd/spi-nor/fsl-quadspi.c new file +6
-0+/* Macros for constructing the LUT register. */ +#define LUT0 (ins, pad, opr) \ + (((opr) << OPRND0_SHIFT) | ((LUT_##pad) << PAD0_SHIFT) | \ + ((LUT_##ins) << INSTR0_SHIFT)) + +#define LUT1 (ins, pad, opr) (LUT0(ins, pad, opr) << OPRND1_SHIFT)
Change this into an inline function, that way you'd get type-checking here.
[...]
drivers/mtd/spi-nor/fsl-quadspi.c line 186
Quoted 3 lines
drivers/mtd/spi-nor/fsl-quadspi.c new file +3
-0+enum fsl_qspi_devtype { +FSL_QUADSPI_VYBRID , +FSL_QUADSPI_IMX6SLX
Will the SLX be only a single-core chip?
drivers/mtd/spi-nor/fsl-quadspi.c line 198
Quoted 12 lines
drivers/mtd/spi-nor/fsl-quadspi.c new file +12
-0+}; + +struct fsl_qspi_devtype_data { +enum fsl_qspi_devtype devtype; +u32 memmap_base; +int rxfifo; +int txfifo; +}; + +static struct fsl_qspi_devtype_data vybrid_data = { + .devtype =FSL_QUADSPI_VYBRID , + .memmap_base =0x20000000 ,
This memmap_base should come from DT prop.
drivers/mtd/spi-nor/fsl-quadspi.c line 200
Quoted 2 lines
drivers/mtd/spi-nor/fsl-quadspi.c new file +2
-0+ .rxfifo = 128, + .txfifo =64
Ditto for both of these too. They're HW props.
Quoted 1 line
+};
[...]
Best regards,
Marek Vasut
PATCH v3 7/7 mtd: spi-nor: Add Freescale QuadSpi driver
Quoted 11 lines · Marek Vasut
On Monday, December 16, 2013 at 09:58:50 AM, Huang Shijie wrote:
[...]drivers/mtd/spi-nor/fsl-quadspi.c line 166
Quoted 6 lines
drivers/mtd/spi-nor/fsl-quadspi.c new file +6
-0+/* Macros for constructing the LUT register. */ +#define LUT0 (ins, pad, opr) \ + (((opr) << OPRND0_SHIFT) | ((LUT_##pad) << PAD0_SHIFT) | \ + ((LUT_##ins) << INSTR0_SHIFT)) + +#define LUT1 (ins, pad, opr) (LUT0(ins, pad, opr) << OPRND1_SHIFT)Change this into an inline function, that way you'd get type-checking here.
Could an inline function do the name-link? such as LUT_##ins ?
Quoted 8 lines
[...]
drivers/mtd/spi-nor/fsl-quadspi.c line 186
Quoted 3 lines
drivers/mtd/spi-nor/fsl-quadspi.c new file +3
-0+enum fsl_qspi_devtype { +FSL_QUADSPI_VYBRID , +FSL_QUADSPI_IMX6SLX Will the SLX be only a single-core chip?
yes.
Quoted 15 lines
drivers/mtd/spi-nor/fsl-quadspi.c line 198
Quoted 13 lines
drivers/mtd/spi-nor/fsl-quadspi.c new file +12
-0+}; + +struct fsl_qspi_devtype_data { +enum fsl_qspi_devtype devtype; +u32 memmap_base; +int rxfifo; +int txfifo; +}; + +static struct fsl_qspi_devtype_data vybrid_data = { + .devtype =FSL_QUADSPI_VYBRID , + .memmap_base =0x20000000 ,This
memmap_baseshould come from DT prop.
yes, i think it should be frome DT property.
Quoted 4 lines
drivers/mtd/spi-nor/fsl-quadspi.c line 200
Quoted 3 lines
drivers/mtd/spi-nor/fsl-quadspi.c new file +2
-0+ .rxfifo = 128, + .txfifo =64
these two depend on the IP, not board specific.
So they should not in the DT.
thanks
Huang Shijie
v3 cover mtd: spi-nor: add a new framework for SPI NOR
In reply to Huang ShijieHi Shijie,
Quoted 1 line
From: Huang Shijie [mailto:b32955 at freescale.com]
[...]
Quoted 9 lines
Huang Shijie (7):
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
mtd: spi-nor: add a helper to find thespi_device_id
Documentation: add the binding file for Quadspi driver
mtd: spi-nor: Add Freescale QuadSpi driver
Quoted 5 lines
.../devicetree/bindings/mtd/fsl-quadspi.txt | 31 + drivers/mtd/Kconfig | 2 + drivers/mtd/Makefile | 1 + drivers/mtd/devices/Kconfig | 2 +- drivers/mtd/devices/m25p80.c | 1271 ++------------------
As much base code is copied from m25p90.c,
Do you mind keeping the sign-offs of the original contributors of m25p80.c at-least in patches where much code is ported ?
This would at-least give some credit to original authors and contributors.
with regards, pekon
v3 cover mtd: spi-nor: add a new framework for SPI NOR
Quoted 4 lines · Pekon
As much base code is copied from
m25p90.c,
Do you mind keeping the sign-offs of the original contributors ofm25p80.cat-least in patches where much code is ported ?
I have added the lines in the spi-nor.c:
" Cloned most of the code from the m25p80.c"
Quoted 1 line
This would at-least give some credit to original authors and contributors.
I do not change any authors information of m25p80.c.
If it is not enough? Could you remind me what to do ?
thanks
Huang Shijie
v3 cover mtd: spi-nor: add a new framework for SPI NOR
Quoted 6 lines
From: Huang Shijie [mailto:b32955 at freescale.com]
Quoted 4 lines · Pekon
As much base code is copied from
m25p90.c,
Do you mind keeping the sign-offs of the original contributors ofm25p80.cat-least in patches where much code is ported ?
Quoted 9 lines
I have added the lines in the
spi-nor.c:" Cloned most of the code from the
m25p80.c"Quoted 1 line
This would at-least give some credit to original authors and contributors.
I do not change any authors information of
m25p80.c.If it is not enough? Could you remind me what to do ?
(1) Add sign-offs of main authors of m25p80, so that original contributors still remains in path of submission [1].
(2) Also, please remove following from spi-nor.c However, you can keep this in fsl-quadspi.c. +MODULE_AUTHOR("Freescale Semiconductor Inc.");
I'm sure this was _not_ present in original m25p80.c
(m25p80.c was started as ST's driver as per MODULE_DESCRIPTION)
(3) +MODULE_LICENSE("GPL");
Also, I assume the license version should be "GPLv2" ?
Request you please _not_ to tag generic driver frameworks with any specific company names, and let open-source be independent of any commercial company tags. Otherwise eventually everything generic driver will have some or other company name associated with it.
And this should be followed by everyone (include myself).
I'm not sure why maintainers are not objecting to this. David, Brian ??
[1] https://www.kernel.org/doc/Documentation/SubmittingPatches
"12) Sign your work"
with regards, pekon
v3 cover mtd: spi-nor: add a new framework for SPI NOR
Quoted 10 lines · Pekon
Quoted 10 lines
From: Huang Shijie [mailto:b32955 at freescale.com]
Quoted 4 lines · Pekon
As much base code is copied from
m25p90.c,
Do you mind keeping the sign-offs of the original contributors ofm25p80.cat-least in patches where much code is ported ?I have added the lines in the
spi-nor.c:" Cloned most of the code from the
m25p80.c"
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
This would at-least give some credit to original authors and contributors.
I do not change any authors information of
m25p80.c.If it is not enough? Could you remind me what to do ?
(1) Add sign-offs of main authors of m25p80, so that original contributors still remains in path of submission [1].
Do you mean add the sign-offs in end of the patch 3's commit message?:
Quoted 6 lines
(2) Also, please remove following from
spi-nor.cHowever, you can keep this infsl-quadspi.c. +MODULE_AUTHOR("Freescale Semiconductor Inc.");
I'm sure this was _not_ present in originalm25p80.c
(m25p80.cwas started as ST's driver as perMODULE_DESCRIPTION)
okay.
Quoted 3 lines
(3) +MODULE_LICENSE("GPL");
Also, I assume the license version should be "GPLv2" ?
yes. it should be v2.
thanks
Huang Shijie
v3 cover mtd: spi-nor: add a new framework for SPI NOR
Quoted 2 lines
From: Huang Shijie [mailto:b32955 at freescale.com]
Quoted 1 line
From: Pekon Gupta [mailto:pekon at ti.com]
[...]
Quoted 5 lines
Quoted 2 lines
(1) Add sign-offs of main authors of m25p80, so that original contributors still remains in path of submission [1].
Do you mean add the sign-offs in end of the patch 3's commit message?:
Signed-off-by Mike Lavender <[email protected]>
I think Mike's email ID is no-more valid. So you can either find out his current email-Id from other sources. OR
add David's or someone else's ID which has equivalent number of contributions in m25p80.c (that you can figure out from either commit logs or git blame).
Quoted 8 lines
Quoted 6 lines
(2) Also, please remove following from
spi-nor.cHowever, you can keep this infsl-quadspi.c. +MODULE_AUTHOR("Freescale Semiconductor Inc.");
I'm sure this was _not_ present in originalm25p80.c
(m25p80.cwas started as ST's driver as perMODULE_DESCRIPTION)okay.
Thanks much.
You can put your name instead, I don't mind that bcoz you have worked to get this framework assembled by joining different pieces.
However, please use a email-id which is valid for long-term (preferably your personal ID), so that even if your association with your company ends, still there is some way to track you and keep you in loop of future patches for this framework.
Quoted 6 lines
Quoted 3 lines
(3) +MODULE_LICENSE("GPL");
Also, I assume the license version should be "GPLv2" ?yes. it should be v2.
with regards, pekon
v3 cover mtd: spi-nor: add a new framework for SPI NOR
Quoted 5 lines · Pekon
Quoted 2 lines
From: Huang Shijie [mailto:b32955 at freescale.com]
Quoted 1 line
From: Pekon Gupta [mailto:pekon at ti.com]
[...]
Quoted 2 lines
Quoted 2 lines
(1) Add sign-offs of main authors of m25p80, so that original contributors still remains in path of submission [1].
Quoted 8 lines
Quoted 3 lines
Do you mean add the sign-offs in end of the patch 3's commit message?:
Signed-off-by Mike Lavender <[email protected]>I think Mike's email ID is no-more valid. So you can either find out his current email-Id from other sources. OR
add David's or someone else's ID which has equivalent number of contributions inm25p80.c(that you can figure out from either commit logs or git blame).
ok, i will find other valid email ID, if i fail, i will add David's.
thanks
Huang Shijie
v3 cover mtd: spi-nor: add a new framework for SPI NOR
In reply to Gupta, PekonQuoted 6 lines · Pekon
Quoted 6 lines
From: Huang Shijie [mailto:b32955 at freescale.com]
Quoted 4 lines · Pekon
As much base code is copied from
m25p90.c,
Do you mind keeping the sign-offs of the original contributors ofm25p80.cat-least in patches where much code is ported ?
Quoted 8 lines
Quoted 8 lines
I have added the lines in the
spi-nor.c:" Cloned most of the code from the
m25p80.c"Quoted 1 line
This would at-least give some credit to original authors and contributors.
I do not change any authors information of
m25p80.c.If it is not enough? Could you remind me what to do ?
In case you clone most of the code from m25p80.c, you need to keep the copyright of that file as well, and add yours on top of it.
Quoted 3 lines
Quoted 1 line
(1) Add sign-offs of main authors of m25p80, so that original contributors still remains in path of submission [1].
The sign-off shouldn't be added by anyone than the person himself. The sign-off tag is generally used in the following cases as far as I know.
1. When the patch is authored, the author A should surely add his sign-off in the first place.
2. If person B submits A's patch with some or without any change on the patch, B should add his sign-off.
3. Maintainer C should add his sign-off when he applies the patch.
In any case, one's sign-off shouldn't be added anyone but himself. I do not see the need to add sign-off of m25p80 authors at the current situation.
Quoted 6 lines
(2) Also, please remove following from
spi-nor.cHowever, you can keep this infsl-quadspi.c. +MODULE_AUTHOR("Freescale Semiconductor Inc.");
I'm sure this was _not_ present in originalm25p80.c
(m25p80.cwas started as ST's driver as perMODULE_DESCRIPTION)
Are you talking about drivers/mtd/devices/m25p80.c? If so, I'm seeing the following lines in the file.
MODULE_LICENSE("GPL");MODULE_AUTHOR("Mike Lavender"); MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips");
I think we should keep the original MODULE_LICENSE and MODULE_AUTHOR, add a new MODULE_AUTHOR("Huang Shijie <[email protected]>") line, and update MODULE_DESCRIPTION line properly.
Quoted 3 lines
(3) +MODULE_LICENSE("GPL");
Also, I assume the license version should be "GPLv2" ?
If this is from original m25p80.c, we shouldn't change it, IMO.
Quoted 4 lines
Request you please _not_ to tag generic driver frameworks with any specific company names, and let open-source be independent of any commercial company tags.
Are you sure about that? Run git grep "redhat" on folder kernel\ and see what you get.
Quoted 2 lines
Otherwise eventually everything generic driver will have some or other company name associated with it.
What's the problem of that? People are paid to do generic work, and why shouldn't their employer's name be mentioned to give the credit. As long as the copyright is GPL, the code can be used, modified and distributed freely, and I do not see any problem with having company name in there.
Shawn
Quoted 10 lines
And this should be followed by everyone (include myself).
I'm not sure why maintainers are not objecting to this. David, Brian ??
[1] https://www.kernel.org/doc/Documentation/SubmittingPatches
"12) Sign your work"with regards, pekon
Hi Shawn,
Quoted 4 lines
From: Shawn Guo [mailto:shawn.guo at linaro.org]
Quoted 3 lines · Pekon
Quoted 2 lines
From: Huang Shijie [mailto:b32955 at freescale.com]
Quoted 1 line · Pekon
[...]
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 3 lines
As much base code is copied from
m25p90.c,
Do you mind keeping the sign-offs of the original contributors ofm25p80.cat-least in patches where much code is ported ?I have added the lines in the
spi-nor.c:" Cloned most of the code from the
m25p80.c"
Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
Quoted 1 line
This would at-least give some credit to original authors and contributors.
I do not change any authors information of
m25p80.c.If it is not enough? Could you remind me what to do ?
In case you clone most of the code from
m25p80.c, you need to keep the copyright of that file as well, and add yours on top of it.
Agree...
Quoted 10 lines
Quoted 3 lines
Quoted 1 line
(1) Add sign-offs of main authors of m25p80, so that original contributors still remains in path of submission [1].
The sign-off shouldn't be added by anyone than the person himself. The sign-off tag is generally used in the following cases as far as I know.
1. When the patch is authored, the author A should surely add his sign-off in the first place.
Quoted 9 lines
2. If person B submits A's patch with some or without any change on the patch, B should add his sign-off.
3. Maintainer C should add his sign-off when he applies the patch.
In any case, one's sign-off shouldn't be added anyone but himself. I do not see the need to add sign-off of m25p80 authors at the current situation.
Agree..
So I meant sign-off with permission from the original authors themselves. And Sign-offs can be multiple (but with permission of-course). OR, you can ask the original author to sign-off for you..
Quoted 10 lines
Quoted 6 lines
(2) Also, please remove following from
spi-nor.cHowever, you can keep this infsl-quadspi.c. +MODULE_AUTHOR("Freescale Semiconductor Inc.");
I'm sure this was _not_ present in originalm25p80.c
(m25p80.cwas started as ST's driver as perMODULE_DESCRIPTION)Are you talking about
drivers/mtd/devices/m25p80.c? If so, I'm seeing the following lines in the file.
Quoted 8 lines
MODULE_LICENSE("GPL");MODULE_AUTHOR("Mike Lavender");MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips");I think we should keep the original
MODULE_LICENSEandMODULE_AUTHOR, add a newMODULE_AUTHOR("Huang Shijie <[email protected]>")line, and updateMODULE_DESCRIPTIONline properly.
As indicated in previous thread also,
if the engineer's association with the company is broken then the email-id in MODULE_AUTHOR becomes invalid. Hence to keep long term tractability of the developer I suggested to use 'personal mail-id' here. MODULE_AUTHOR should have a email-id which is valid for long term, because you might need to at-least loop-in Author in longer time when there are some bug-fix or considerable code change.
(This problem was also pointed out earlier in one of the emails by greg-kh,
But I'm unable to trace that now).
Quoted 6 lines
Quoted 3 lines
(3) +MODULE_LICENSE("GPL");
Also, I assume the license version should be "GPLv2" ?If this is from original
m25p80.c, we shouldn't change it, IMO.
As I can understand from general threads on google.
GPLv2 gives some additional protection to free-software companies from patent litigations of proprietary software companies. As this code is not exact replica of m25p80.c, so it should be made GPLv2 or better .. But sincerely, I do not have too much knowledge into this,
So I'll let maintainers decide if they see benefit in moving to GPLv2 ?
Quoted 8 lines
Quoted 4 lines
Request you please _not_ to tag generic driver frameworks with any specific company names, and let open-source be independent of any commercial company tags.
Are you sure about that? Run git grep "redhat" on folder kernel\ and see what you get.
Something which may have been done repeatedly in past, may not mean it is correct OR the only way to do it. :-)
Quoted 9 lines
Quoted 2 lines
Otherwise eventually everything generic driver will have some or other company name associated with it.
What's the problem of that? People are paid to do generic work, and why shouldn't their employer's name be mentioned to give the credit. As long as the copyright is GPL, the code can be used, modified and distributed freely, and I do not see any problem with having company name in there.
It's not about who is taking credit. It's about how will you track the developer if after few years you want some significant changes in the code he wrote. You would agree, it's difficult to track developers just by their company names or company IDs.
It's perfectly okay, if you want to give credits of your work to anyone (whether any company or individual). But that you can mention in commit logs.
All I said was using company names in Headers or MODULE_AUTHOR of *generic frameworks*. A generic framework is maintained and updated by community at large. And over course of time other people contribute more than the author. So tagging a company name there would sound like _repeatedly_ giving credit to company or yourself, even if most of the original code is changed now. Does that make sense ?
So, I just suggested to keep generic framework code free from all these. However, You are free to do anything in your controller specific code.
with regards, pekon
Quoted 6 lines · Pekon
All I said was using company names in Headers or
MODULE_AUTHORof *generic frameworks*. A generic framework is maintained and updated by community at large. And over course of time other people contribute more than the author. So tagging a company name there would sound like _repeatedly_ giving credit to company or yourself, even if most of the original code is changed now. Does that make sense ?
I could somehow buy in the argument of using person email over company one in MODULE_AUTHOR(), but still not the one that do not use company name in Headers.
In this case, Huang works for Freescale and Freescale pays him to do the work, so Huang shares the authorship and Freescale shares the copyright. There is nothing wrong adding Freescale copyright into the file header, based on my understanding. When other people make significant changes and contributions to the file, they are welcomed to add more copyright info on top of the existing ones.
I'm not a lawyer, and more than happy to be corrected if I'm wrong.
Shawn