sf: fix support of QSPI memories and controllers
Subsystems (6)
cover sf: fix support of QSPI memories and controllers
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a memory.
Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: call spi_claim_bus() and spi_release_bus() only once per read,
write or erase
sf: replace spi_flash_read_common() calls by spi_flash_cmd_read()
sf: remove spi_flash_write_common()
sf: export spi_flash_wait_ready() function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into generic spi_flash_write_alg()
sf: fix selection of supported READ commands for QSPI memories
sf: fix detection of QSPI memories when they boot in Quad or Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controller
arch/arm/mach-at91/include/mach/clk.h | 5 + drivers/mtd/spi/Kconfig | 18 +- drivers/mtd/spi/Makefile | 2 + drivers/mtd/spi/atmel_qspi_flash.c | 432 ++++++++++++++++++++ drivers/mtd/spi/sf-uclass.c | 11 + drivers/mtd/spi/sf_internal.h | 115 ++++-- drivers/mtd/spi/sf_micron.c | 222 ++++++++++ drivers/mtd/spi/sf_params.c | 32 +- drivers/mtd/spi/sf_probe.c | 46 ++- drivers/mtd/spi/spi_flash.c | 744 +++++++++++++++++++++------------- drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/atmel_qspi.c | 150 +++++++ drivers/spi/atmel_qspi.h | 145 +++++++ include/spi_flash.h | 105 +++++ 15 files changed, 1701 insertions(+), 336 deletions(-) create mode 100644 drivers/mtd/spi/atmel_qspi_flash.c create mode 100644 drivers/mtd/spi/sf_micron.c create mode 100644 drivers/spi/atmel_qspi.c create mode 100644 drivers/spi/atmel_qspi.h
Signature · 1 line
1.8.2.2
PATCH 1/18 Revert "sf: Fix quad bit set for micron devices"
This reverts commit c56ae7519f141523ba1248b22b5b5169b21772fe.
Once the 'Quad Enable' bit is cleared in their Enhanced Volatile Configuration Register (EVCR), Micron memories expect ALL commands to use the SPI 4-4-4 protocol. Commands using SPI 1-y-z protocols are no longer accepted.
Within the reverted commit, the write_evcr() function is implemented using the spi_flash_write_common(), which is a shortcut for the
[ spi_flash_cmd_write_enable(), spi_flash_cmd_write(), spi_flash_cmd_wait_ready() ] sequence.
Since the internal state of the Micron memory has been changed when the spi_flash_cmd_write() function completes, the later call of the spi_flash_cmd_wait_ready() function fails.
Indeed the SPI controller driver is not aware of the SPI protocol switch.
Further patches will fix the support of Micron QSPI memories.
--- drivers/mtd/spi/sf_internal.h | 3 --- drivers/mtd/spi/spi_flash.c | 62 ++----------------------------------------- 2 files changed, 2 insertions(+), 63 deletions(-)
drivers/mtd/spi/sf_internal.h +0 -3
@@ -77,7 +77,6 @@ enum spi_nor_option_flags {#define CMD_WRITE_DISABLE 0x04#define CMD_WRITE_ENABLE 0x06#define CMD_QUAD_PAGE_PROGRAM 0x32 -#define CMD_WRITE_EVCR 0x61/* Read commands */ #define CMD_READ_ARRAY_SLOW 0x03
@@ -91,7 +90,6 @@ enum spi_nor_option_flags {#define CMD_READ_STATUS1 0x35#define CMD_READ_CONFIG 0x35#define CMD_FLAG_STATUS 0x70 -#define CMD_READ_EVCR 0x65/* Bank addr access commands */ #ifdef CONFIG_SPI_FLASH_BAR
@@ -106,7 +104,6 @@ enum spi_nor_option_flags {#define STATUS_QEB_WINSPAN BIT(1)#define STATUS_QEB_MXIC BIT(6)#define STATUS_PEC BIT(7) -#define STATUS_QEB_MICRON BIT(7)#define SR_BP0 BIT(2)/* Block protect 0 */ #define SR_BP1 BIT(3)/* Block protect 1 */ #define SR_BP2 BIT(4)/* Block protect 2 */
drivers/mtd/spi/spi_flash.c +2 -60
80 lines not on this page · raw message
Signature · 1 line
1.8.2.2
PATCH 2/18 sf: call spi_claim_bus() and spi_release_bus() only once per read, write or erase
In reply to Cyrille PitchenThere is no need to claim/release the SPI bus for each command sent to the memory when performing read, write or erase operations. Now we claim the SPI bus once for all at the very beginning of these operations then we release it just before exiting.
--- drivers/mtd/spi/sf_internal.h | 5 +--- drivers/mtd/spi/spi_flash.c | 68 +++++++++++++++++++++++++------------------ 2 files changed, 40 insertions(+), 33 deletions(-)
drivers/mtd/spi/sf_internal.h +1 -4
@@ -192,11 +192,9 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)/* * Used for spi_flash write operation -* - SPI claim * - spi_flash_cmd_write_enable * - spi_flash_cmd_write * - spi_flash_cmd_wait_ready -* - SPI release */ int spi_flash_write_common (struct spi_flash *flash,const u8 *cmd,size_t cmd_len,const void *buf,size_t buf_len);
@@ -210,8 +208,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, size_t len, const void *buf);/* -* Same as spi_flash_cmd_read() except it also claims/releases the SPI -* bus. Used as common part of the ->read() operation. +* Same as spi_flash_cmd_read(). Used as common part of the ->read() operation. */ int spi_flash_read_common (struct spi_flash *flash,const u8 *cmd,size_t cmd_len,void *data,size_t data_len);
drivers/mtd/spi/spi_flash.c +39 -29
170 lines not on this page · raw message
Signature · 1 line
1.8.2.2
PATCH 3/18 sf: replace spi_flash_read_common() calls by spi_flash_cmd_read()
In reply to Cyrille PitchenSince spi_claim_bus() and spi_release_bus() are now called outside spi_flash_read_common(), this latest function is just a useless alias for spi_flash_cmd_read(). So we remove it.
--- drivers/mtd/spi/sf_internal.h | 6 ------ drivers/mtd/spi/spi_flash.c | 30 +++++++++--------------------- 2 files changed, 9 insertions(+), 27 deletions(-)
drivers/mtd/spi/sf_internal.h +0 -6
@@ -207,12 +207,6 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,int spi_flash_cmd_write_ops (struct spi_flash *flash,u32 offset,size_t len,const void *buf); -/* -* Same as spi_flash_cmd_read(). Used as common part of the ->read() operation. -*/ -int spi_flash_read_common (struct spi_flash *flash,const u8 *cmd, -size_t cmd_len,void *data,size_t data_len); -/* Flash read operation, support all possible read commands */ int spi_flash_cmd_read_ops (struct spi_flash *flash,u32 offset,size_t len,void *data);
drivers/mtd/spi/spi_flash.c +9 -21
@@ -32,11 +32,12 @@ static void spi_flash_addr(u32 addr, u8 *cmd)static int read_sr (struct spi_flash *flash,u8 *rs) { +struct spi_slave *spi = flash->spi;int ret;u8 cmd; cmd =CMD_READ_STATUS ; - ret =spi_flash_read_common (flash, &cmd,1 , rs,1 ); + ret =spi_flash_cmd_read (spi, &cmd,1 , rs,1 );if (ret <0 ) {debug ("SF: fail to read status register\n" );return ret;
@@ -47,10 +48,11 @@ static int read_sr(struct spi_flash *flash, u8 *rs)static int read_fsr (struct spi_flash *flash,u8 *fsr) { +struct spi_slave *spi = flash->spi;int ret;const u8 cmd =CMD_FLAG_STATUS ; - ret =spi_flash_read_common (flash, &cmd,1 , fsr,1 ); + ret =spi_flash_cmd_read (spi, &cmd,1 , fsr,1 );if (ret <0 ) {debug ("SF: fail to read flag status register\n" );return ret;
@@ -77,11 +79,12 @@ static int write_sr(struct spi_flash *flash, u8 ws)#if defined(CONFIG_SPI_FLASH_SPANSION ) || defined(CONFIG_SPI_FLASH_WINBOND )static int read_cr (struct spi_flash *flash,u8 *rc) { +struct spi_slave *spi = flash->spi;int ret;u8 cmd; cmd =CMD_READ_CONFIG ; - ret =spi_flash_read_common (flash, &cmd,1 , rc,1 ); + ret =spi_flash_cmd_read (spi, &cmd,1 , rc,1 );if (ret <0 ) {debug ("SF: fail to read config register\n" );return ret;
@@ -136,6 +139,7 @@ bar_end:static int spi_flash_read_bar (struct spi_flash *flash,u8 idcode0) { +struct spi_slave *spi = flash->spi;u8 curr_bank =0 ;int ret;
@@ -152,8 +156,7 @@ static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0) flash->bank_write_cmd =CMD_EXTNADDR_WREAR ; } - ret =spi_flash_read_common (flash, &flash->bank_read_cmd,1 , - &curr_bank,1 ); + ret =spi_flash_cmd_read (spi, &flash->bank_read_cmd,1 , &curr_bank,1 );if (ret) {debug ("SF: fail to read bank addr register\n" );return ret;
@@ -414,21 +417,6 @@ release:return ret; } -int spi_flash_read_common (struct spi_flash *flash,const u8 *cmd, -size_t cmd_len,void *data,size_t data_len) -{ -struct spi_slave *spi = flash->spi; -int ret; - - ret =spi_flash_cmd_read (spi, cmd, cmd_len, data, data_len); -if (ret <0 ) { -debug ("SF: read cmd failed\n" ); -return ret; - } - -return ret; -} -/* * TODO: remove the weak after all the other spi_flash_copy_mmap * implementations removed from drivers
@@ -496,7 +484,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,spi_flash_addr (read_addr, cmd); - ret =spi_flash_read_common (flash, cmd, cmdsz, data, read_len); + ret =spi_flash_cmd_read (spi, cmd, cmdsz, data, read_len);if (ret <0 ) {debug ("SF: read failed\n" );break ;
Signature · 1 line
1.8.2.2
PATCH 4/18 sf: remove spi_flash_write_common()
In reply to Cyrille PitchenThis patch prepares the split of memory versus internal registers SPI commands.
--- drivers/mtd/spi/sf_internal.h | 8 +++--- drivers/mtd/spi/spi_flash.c | 62 ++++++++++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 28 deletions(-)
drivers/mtd/spi/sf_internal.h +4 -4
@@ -191,13 +191,13 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) }/* -* Used for spi_flash write operation +* Used for spi_flash register update operation * - spi_flash_cmd_write_enable -* - spi_flash_cmd_write +* - write new register value * - spi_flash_cmd_wait_ready */ -int spi_flash_write_common (struct spi_flash *flash,const u8 *cmd, -size_t cmd_len,const void *buf,size_t buf_len); +int spi_flash_update_reg (struct spi_flash *flash,u8 opcode,size_t len, +const void *buf);/* * Flash write operation, support all possible write commands.
drivers/mtd/spi/spi_flash.c +38 -24
152 lines not on this page · raw message
Signature · 1 line
1.8.2.2
PATCH 5/18 sf: export spi_flash_wait_ready() function
In reply to Cyrille PitchenThis patch exports a new function so future drivers can use it.
--- drivers/mtd/spi/sf_internal.h | 3 +++ drivers/mtd/spi/spi_flash.c | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-)
drivers/mtd/spi/sf_internal.h +3 -0
@@ -190,6 +190,9 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)return spi_flash_cmd (flash->spi,CMD_WRITE_DISABLE ,NULL ,0 ); } +/* Wait for Busy/Write in Progress flag to be cleared */ +int spi_flash_wait_ready (struct spi_flash *flash); +/* * Used for spi_flash register update operation * - spi_flash_cmd_write_enable
drivers/mtd/spi/spi_flash.c +6 -1
@@ -249,6 +249,11 @@ static int spi_flash_cmd_wait_ready(struct spi_flash *flash,return -ETIMEDOUT ; } +int spi_flash_wait_ready (struct spi_flash *flash) +{ +return spi_flash_cmd_wait_ready (flash,SPI_FLASH_PROG_TIMEOUT ); +} +int spi_flash_update_reg (struct spi_flash *flash,u8 opcode,size_t len,const void *buf) {
@@ -267,7 +272,7 @@ int spi_flash_update_reg(struct spi_flash *flash, u8 opcode,return ret; } - ret =spi_flash_cmd_wait_ready (flash,SPI_FLASH_PROG_TIMEOUT ); + ret =spi_flash_wait_ready (flash);if (ret <0 ) {debug ("SF: write register timed out\n" );return ret;
Signature · 1 line
1.8.2.2
PATCH 6/18 sf: share erase generic algorithm
In reply to Cyrille PitchenThis patch splits the generic algorithm to erase pages/sectors from the actual implementation which is specific to each UCLASS_SPI_FLASH driver.
For now, the sf_probe.c driver is the only instance of this driver class using this generic algorithm but other driver instances are to come. This patch will ease their implementation.
Please note that the sf_dataflash.c driver has its own implementation of the .erase hook (of the struct dm_spi_flash_ops) which is not compatible with this generic algorithm. This is why we can't simply change the prototype of .erase hook and create a spi_flash_erase() wrapper.
--- drivers/mtd/spi/sf_internal.h | 4 ++++ drivers/mtd/spi/spi_flash.c | 28 +++++++++++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-)
drivers/mtd/spi/sf_internal.h +4 -0
@@ -169,6 +169,10 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,/* Flash erase(sectors) operation, support all possible erase commands */ int spi_flash_cmd_erase_ops (struct spi_flash *flash,u32 offset,size_t len); +typedef int (*spi_flash_erase_fn )(struct spi_flash *,u32 ); +int spi_flash_erase_alg (struct spi_flash *flash,u32 offset,size_t len, +spi_flash_erase_fn erase_fn); +/* Lock stmicro spi flash region */ int stm_lock (struct spi_flash *flash,u32 ofs,size_t len);
drivers/mtd/spi/spi_flash.c +19 -9
@@ -281,11 +281,11 @@ int spi_flash_update_reg(struct spi_flash *flash, u8 opcode,return 0 ; } -int spi_flash_cmd_erase_ops (struct spi_flash *flash,u32 offset,size_t len) +int spi_flash_erase_alg (struct spi_flash *flash,u32 offset,size_t len, +spi_flash_erase_fn erase_fn) {struct spi_slave *spi = flash->spi;u32 erase_size, erase_addr; -u8 cmd[SPI_FLASH_CMD_LEN ];int ret =-1 ; erase_size = flash->erase_size;
@@ -309,7 +309,6 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) } } - cmd[0 ] = flash->erase_cmd;while (len) { erase_addr = offset;
@@ -328,12 +327,8 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)break ; } -spi_flash_addr (erase_addr, cmd); - -debug ("SF: erase %2x %2x %2x %2x (%x)\n" , cmd[0 ], cmd[1 ], - cmd[2 ], cmd[3 ], erase_addr); - - ret =spi_flash_cmd_write (spi, cmd,sizeof (cmd),NULL ,0 ); +debug ("SF: erase %2x %06x\n" , flash->erase_cmd, erase_addr); + ret =erase_fn (flash, erase_addr);if (ret <0 ) {debug ("SF: erase failed\n" );break ;
@@ -356,6 +351,21 @@ release:return ret; } +static int spi_flash_erase_impl (struct spi_flash *flash,u32 offset) +{ +struct spi_slave *spi = flash->spi; +u8 cmd[SPI_FLASH_CMD_LEN ]; + + cmd[0 ] = flash->erase_cmd; +spi_flash_addr (offset, cmd); +return spi_flash_cmd_write (spi, cmd,sizeof (cmd),NULL ,0 ); +} + +int spi_flash_cmd_erase_ops (struct spi_flash *flash,u32 offset,size_t len) +{ +return spi_flash_erase_alg (flash, offset, len, spi_flash_erase_impl); +} +int spi_flash_cmd_write_ops (struct spi_flash *flash,u32 offset,size_t len,const void *buf) {
Signature · 1 line
1.8.2.2
PATCH 7/18 sf: share write generic algorithm
In reply to Cyrille PitchenThis patch splits the generic algorithm to write data from the actual implementation which is specific to each UCLASS_SPI_FLASH driver.
For now, the sf_probe.c driver is the only instance of this driver class using this generic algorithm but other driver instances are to come. This patch will ease their implementation.
Please note that the sf_dataflash.c driver has its own implementation of the .write hook (of the struct dm_spi_flash_ops) which is not compatible with this generic algorithm. This is why we can't simply change the prototype of .write hook and create a spi_flash_write() wrapper.
--- drivers/mtd/spi/sf_internal.h | 5 +++++ drivers/mtd/spi/spi_flash.c | 34 ++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-)
drivers/mtd/spi/sf_internal.h +5 -0
@@ -214,6 +214,11 @@ int spi_flash_update_reg(struct spi_flash *flash, u8 opcode, size_t len,int spi_flash_cmd_write_ops (struct spi_flash *flash,u32 offset,size_t len,const void *buf); +typedef int (*spi_flash_write_fn )(struct spi_flash *,u32 ,size_t , +const void *); +int spi_flash_write_alg (struct spi_flash *flash,u32 offset,size_t len, +const void *buf,spi_flash_write_fn write_fn); +/* Flash read operation, support all possible read commands */ int spi_flash_cmd_read_ops (struct spi_flash *flash,u32 offset,size_t len,void *data);
drivers/mtd/spi/spi_flash.c +24 -10
@@ -366,14 +366,13 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)return spi_flash_erase_alg (flash, offset, len, spi_flash_erase_impl); } -int spi_flash_cmd_write_ops (struct spi_flash *flash,u32 offset, -size_t len,const void *buf) +int spi_flash_write_alg (struct spi_flash *flash,u32 offset,size_t len, +const void *buf,spi_flash_write_fn write_fn) {struct spi_slave *spi = flash->spi;unsigned long byte_addr, page_size;u32 write_addr;size_t chunk_len, actual; -u8 cmd[SPI_FLASH_CMD_LEN ];int ret =-1 ; page_size = flash->page_size;
@@ -393,7 +392,6 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, } } - cmd[0 ] = flash->write_cmd;for (actual =0 ; actual < len; actual += chunk_len) { write_addr = offset;
@@ -419,13 +417,10 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,break ; } -spi_flash_addr (write_addr, cmd); - -debug ("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n" , - buf + actual, cmd[0 ], cmd[1 ], cmd[2 ], cmd[3 ], chunk_len); +debug ("SF: 0x%p => cmd = { 0x%02x 0x%06x } chunk_len = %zu\n" , + buf + actual, flash->write_cmd, write_addr, chunk_len); - ret =spi_flash_cmd_write (spi, cmd,sizeof (cmd), - buf + actual, chunk_len); + ret =write_fn (flash, write_addr, chunk_len, buf + actual);if (ret <0 ) {debug ("SF: write failed\n" );break ;
@@ -446,6 +441,25 @@ release:return ret; } +static int spi_flash_write_impl (struct spi_flash *flash,u32 offset, +size_t len,const void *buf) +{ +struct spi_slave *spi = flash->spi; +u8 cmd[SPI_FLASH_CMD_LEN ]; +size_t cmdsz =sizeof (cmd); + + cmd[0 ] = flash->write_cmd; +spi_flash_addr (offset, cmd); +return spi_flash_cmd_write (spi, cmd, cmdsz, buf, len); +} + +int spi_flash_cmd_write_ops (struct spi_flash *flash,u32 offset, +size_t len,const void *buf) +{ +return spi_flash_write_alg (flash, offset, len, buf, + spi_flash_write_impl); +} +/* * TODO: remove the weak after all the other spi_flash_copy_mmap * implementations removed from drivers
Signature · 1 line
1.8.2.2
PATCH 8/18 sf: share read generic algorithm
In reply to Cyrille PitchenThis patch splits the generic algorithm to read data from the actual implementation which is specific to each UCLASS_SPI_FLASH driver.
For now, the sf_probe.c driver is the only instance of this driver class using this generic algorithm but other driver instances are to come. This patch will ease their implementation.
Please note that the sf_dataflash.c driver has its own implementation of the .read hook (of the struct dm_spi_flash_ops) which is not compatible with this generic algorithm. This is why we can't simply change the prototype of .read hook and create a spi_flash_read() wrapper.
--- drivers/mtd/spi/sf_internal.h | 4 ++++ drivers/mtd/spi/spi_flash.c | 48 ++++++++++++++++++++++++++++--------------- 2 files changed, 35 insertions(+), 17 deletions(-)
drivers/mtd/spi/sf_internal.h +4 -0
@@ -223,6 +223,10 @@ int spi_flash_write_alg(struct spi_flash *flash, u32 offset, size_t len,int spi_flash_cmd_read_ops (struct spi_flash *flash,u32 offset,size_t len,void *data); +typedef int (*spi_flash_read_fn )(struct spi_flash *,u32 ,size_t ,void *); +int spi_flash_read_alg (struct spi_flash *flash,u32 offset,size_t len, +void *data,spi_flash_read_fn read_fn); +#ifdef CONFIG_SPI_FLASH_MTD int spi_flash_mtd_register (struct spi_flash *flash);void spi_flash_mtd_unregister (void );
drivers/mtd/spi/spi_flash.c +31 -17
80 lines not on this page · raw message
Signature · 1 line
1.8.2.2
PATCH 9/18 sf: add hooks to handle register read and write operations
In reply to Cyrille PitchenThis patch finalizes the split of internal register and memory data SPI commands. Indeed some (Q)SPI controllers such as the Atmel QSPI controller need to make the difference between register read/write SPI commands and data read/write/erase SPI commands.
It follows an interface close to the one used by the spi-nor.c driver in Linux:
- read_reg: read out the register - write_reg: write data to the register - read: read data from the SPI flash - write: write data into the SPI flash - erase: erase sectors of the SPI flash
--- drivers/mtd/spi/sf-uclass.c | 11 +++++++ drivers/mtd/spi/sf_internal.h | 13 ++++++-- drivers/mtd/spi/sf_probe.c | 18 +++++++++++ drivers/mtd/spi/spi_flash.c | 70 ++++++++++++++++++++++++------------------- include/spi_flash.h | 58 +++++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 33 deletions(-)
drivers/mtd/spi/sf-uclass.c +11 -0
@@ -13,6 +13,17 @@DECLARE_GLOBAL_DATA_PTR ; +int spi_flash_read_reg_dm (struct udevice *dev,u8 opcode,size_t len,void *buf) +{ +return sf_get_ops (dev)->read_reg (dev, opcode, len, buf); +} + +int spi_flash_write_reg_dm (struct udevice *dev,u8 opcode,size_t len, +const void *buf) +{ +return sf_get_ops (dev)->write_reg (dev, opcode, len, buf); +} +int spi_flash_read_dm (struct udevice *dev,u32 offset,size_t len,void *buf) {return sf_get_ops (dev)->read (dev, offset, len, buf);
drivers/mtd/spi/sf_internal.h +11 -2
@@ -12,6 +12,7 @@#include <linux/types.h> #include <linux/compiler.h> +#include <spi_flash.h> /* Dual SPI flash memories - see SPI_COMM_DUAL_... */ enum spi_dual_flash {
@@ -185,13 +186,13 @@ int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len);/* Enable writing on the SPI flash */ static inline int spi_flash_cmd_write_enable (struct spi_flash *flash) { -return spi_flash_cmd (flash->spi,CMD_WRITE_ENABLE ,NULL ,0 ); +return spi_flash_write_reg (flash,CMD_WRITE_ENABLE ,0 ,NULL ); }/* Disable writing on the SPI flash */ static inline int spi_flash_cmd_write_disable (struct spi_flash *flash) { -return spi_flash_cmd (flash->spi,CMD_WRITE_DISABLE ,NULL ,0 ); +return spi_flash_write_reg (flash,CMD_WRITE_DISABLE ,0 ,NULL ); }/* Wait for Busy/Write in Progress flag to be cleared */
@@ -206,6 +207,10 @@ int spi_flash_wait_ready(struct spi_flash *flash);int spi_flash_update_reg (struct spi_flash *flash,u8 opcode,size_t len,const void *buf); +/* Flash write register operation */ +int spi_flash_cmd_write_reg_ops (struct spi_flash *flash,u8 opcode,size_t len, +const void *buf); +/* * Flash write operation, support all possible write commands. * Write the requested data out breaking it up into multiple write
@@ -219,6 +224,10 @@ typedef int (*spi_flash_write_fn)(struct spi_flash *, u32, size_t,int spi_flash_write_alg (struct spi_flash *flash,u32 offset,size_t len,const void *buf,spi_flash_write_fn write_fn); +/* Flash read register operation */ +int spi_flash_cmd_read_reg_ops (struct spi_flash *flash,u8 opcode,size_t len, +void *buf); +/* Flash read operation, support all possible read commands */ int spi_flash_cmd_read_ops (struct spi_flash *flash,u32 offset,size_t len,void *data);
drivers/mtd/spi/sf_probe.c +18 -0
@@ -111,6 +111,22 @@ void spi_flash_free(struct spi_flash *flash)#else /* defined CONFIG_DM_SPI_FLASH */ +static int spi_flash_std_read_reg (struct udevice *dev,u8 opcode,size_t len, +void *buf) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_read_reg_ops (flash, opcode, len, buf); +} + +static int spi_flash_std_write_reg (struct udevice *dev,u8 opcode,size_t len, +const void *buf) +{ +struct spi_flash *flash =dev_get_uclass_priv (dev); + +return spi_flash_cmd_write_reg_ops (flash, opcode, len, buf); +} +static int spi_flash_std_read (struct udevice *dev,u32 offset,size_t len,void *buf) {
@@ -157,6 +173,8 @@ static int spi_flash_std_probe(struct udevice *dev) }static const struct dm_spi_flash_ops spi_flash_std_ops = { + .read_reg = spi_flash_std_read_reg, + .write_reg = spi_flash_std_write_reg, .read = spi_flash_std_read, .write = spi_flash_std_write, .erase = spi_flash_std_erase,
drivers/mtd/spi/spi_flash.c +39 -31
143 lines not on this page · raw message
include/spi_flash.h +58 -0
94 lines not on this page · raw message
Signature · 1 line
1.8.2.2
PATCH 10/18 sf: move support of SST flash into generic spi_flash_write_alg()
In reply to Cyrille PitchenThis patch makes the support of SST flashes available to all UCLASS_SPI_FLASH drivers, not only the sf_probe.c one.
--- drivers/mtd/spi/sf_internal.h | 8 ++--- drivers/mtd/spi/sf_probe.c | 9 ----- drivers/mtd/spi/spi_flash.c | 76 +++++++++++++++++++++++-------------------- 3 files changed, 43 insertions(+), 50 deletions(-)
drivers/mtd/spi/sf_internal.h +2 -6
@@ -51,7 +51,8 @@ enum {enum spi_nor_option_flags {SNOR_F_SST_WR =BIT (0 ), -SNOR_F_USE_FSR =BIT (1 ), +SNOR_F_SST_WR_2ND =BIT (1 ), +SNOR_F_USE_FSR =BIT (2 ), };#define SPI_FLASH_3B_ADDR_LEN 3
@@ -118,11 +119,6 @@ enum spi_nor_option_flags {#ifdef CONFIG_SPI_FLASH_SST # define CMD_SST_BP 0x02/* Byte Program */ # define CMD_SST_AAI_WP 0xAD/* Auto Address Incr Word Program */ - -int sst_write_wp (struct spi_flash *flash,u32 offset,size_t len, -const void *buf); -int sst_write_bp (struct spi_flash *flash,u32 offset,size_t len, -const void *buf);#endif /**
drivers/mtd/spi/sf_probe.c +0 -9
@@ -140,15 +140,6 @@ static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, {struct spi_flash *flash =dev_get_uclass_priv (dev); -#if defined(CONFIG_SPI_FLASH_SST ) -if (flash->flags &SNOR_F_SST_WR ) { -if (flash->spi->mode &SPI_TX_BYTE ) -return sst_write_bp (flash, offset, len, buf); -else -return sst_write_wp (flash, offset, len, buf); - } -#endif -return spi_flash_cmd_write_ops (flash, offset, len, buf); }
drivers/mtd/spi/spi_flash.c +41 -35
171 lines not on this page · raw message
Signature · 1 line
1.8.2.2
PATCH 11/18 sf: fix selection of supported READ commands for QSPI memories
In reply to Cyrille PitchenIt looks odd to compute a logical AND between the e_rd_cmd field of struct spi_flash_params and the mode_rx field of struct spi_slave.
Indeed, these two fields don't use the same range of values. mode_rx is limited to SPI_RX_{SLOW, FAST, DUAL, QUAD}. Even completed with the SPI_TX_{DUAL, QUAD} flags from the mode field, this is not enough to find out whether the SPI controller driver supports Fast Read 4-4-4 (Micron, Macronix, Winbond) commands.
With only the SPI_RX_QUAD and the SPI_TX_QUAD, how to make the difference between Fast Read 1-4-4 and Fast Read 4-4-4 ?
On the other hand, the e_rd_cmd field already provides a more accurate knowledge of the Fast Read commands supported by the SPI flash memory.
Then this patch provides a safe convertion from mode_rx + mode values into e_rd_cmd values to be used by the sf_probe.c driver: this driver never try using the Fast Read 4-4-4 command.
Other drivers will provide an exhaustive list of supported Fast Read commands.
Hence a more accurate op code is chosen according to both the SPI flash memory and the SPI controller capabilities.
Please note that we cannot simply extend the SPI_TX_* and SPI_RX_* flags of the struct spi_slave since they are set according DT properties shared with Linux: spi-tx-bus-width and spi-rx-bus-width.
These two DT properties don't allow us to make the difference between the SPI 1-4-4 and SPI 4-4-4 protocols.
--- drivers/mtd/spi/sf_internal.h | 14 +++++++++++--- drivers/mtd/spi/sf_params.c | 32 ++++++++++++++++---------------- drivers/mtd/spi/sf_probe.c | 19 ++++++++++++++++++- drivers/mtd/spi/spi_flash.c | 9 ++++++--- 4 files changed, 51 insertions(+), 23 deletions(-)
drivers/mtd/spi/sf_internal.h +11 -3
@@ -29,12 +29,19 @@ enum spi_read_cmds {QUAD_OUTPUT_FAST =BIT (3 ),DUAL_IO_FAST =BIT (4 ),QUAD_IO_FAST =BIT (5 ), +DUAL_CMD_FAST =BIT (6 ), + QUAD_CMD_FAST = BIT(7), };/* Normal - Extended - Full command set */ #define RD_NORM (ARRAY_SLOW | ARRAY_FAST) -#define RD_EXTN (RD_NORM | DUAL_OUTPUT_FAST | DUAL_IO_FAST) -#define RD_FULL (RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST) +#define RD_EXTN (RD_NORM | DUAL_OUTPUT_FAST) +#define RD_DUAL (RD_NORM | DUAL_OUTPUT_FAST | DUAL_IO_FAST) +#define RD_DCMD (RD_DUAL | DUAL_CMD_FAST) +#define RD_QUAD (RD_NORM | QUAD_OUTPUT_FAST | QUAD_IO_FAST) +#define RD_QCMD (RD_QUAD | QUAD_CMD_FAST) +#define RD_FULL (RD_DUAL | RD_QUAD) +#define RD_FCMD (RD_DCMD | RD_QCMD)/* sf param flags */ enum {
@@ -240,6 +247,7 @@ void spi_flash_mtd_unregister(void);/** * spi_flash_scan - scan the SPI FLASH * @flash: the spi flash structure +* @e_rd_cmd: Enum list for read commands supported by the SPI controller * * The drivers can use this fuction to scan the SPI FLASH. * In the scanning, it will try to get all the necessary information to
@@ -247,6 +255,6 @@ void spi_flash_mtd_unregister(void);* * Return: 0 for success, others for failure. */ -int spi_flash_scan (struct spi_flash *flash); +int spi_flash_scan (struct spi_flash *flash,u8 e_rd_cmd);#endif /* _SF_INTERNAL_H_ */
drivers/mtd/spi/sf_params.c +16 -16
@@ -47,10 +47,10 @@ const struct spi_flash_params spi_flash_params_table[] = { {"MX25L1605D", 0xc22015, 0x0, 64 * 1024, 32, RD_NORM, 0}, {"MX25L3205D", 0xc22016, 0x0, 64 * 1024, 64, RD_NORM, 0}, {"MX25L6405D", 0xc22017, 0x0, 64 * 1024, 128, RD_NORM, 0}, - {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, - {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP}, - {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP}, - {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, + {"MX25L12805", 0xc22018, 0x0, 64 * 1024, 256, RD_QCMD, WR_QPP}, + {"MX25L25635F", 0xc22019, 0x0, 64 * 1024, 512, RD_QCMD, WR_QPP}, + {"MX25L51235F", 0xc2201a, 0x0, 64 * 1024, 1024, RD_QCMD, WR_QPP}, + {"MX25L12855E", 0xc22618, 0x0, 64 * 1024, 256, RD_QCMD, WR_QPP}, #endif #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */ {"S25FL008A", 0x010213, 0x0, 64 * 1024, 16, RD_NORM, 0},
@@ -83,18 +83,18 @@ const struct spi_flash_params spi_flash_params_table[] = { {"M25P64", 0x202017, 0x0, 64 * 1024, 128, RD_NORM, 0}, {"M25P128", 0x202018, 0x0, 256 * 1024, 64, RD_NORM, 0}, {"M25PX64", 0x207117, 0x0, 64 * 1024, 128, RD_NORM, SECT_4K}, - {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, - {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, RD_FULL, WR_QPP}, - {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, RD_FULL, WR_QPP | SECT_4K}, - {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP | E_FSR | SECT_4K}, - {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, RD_FULL, WR_QPP | E_FSR | SECT_4K}, - {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, RD_FULL, WR_QPP | E_FSR | SECT_4K}, - {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, RD_FULL, WR_QPP | E_FSR | SECT_4K}, + {"N25Q32", 0x20ba16, 0x0, 64 * 1024, 64, RD_FCMD, WR_QPP | SECT_4K}, + {"N25Q32A", 0x20bb16, 0x0, 64 * 1024, 64, RD_FCMD, WR_QPP | SECT_4K}, + {"N25Q64", 0x20ba17, 0x0, 64 * 1024, 128, RD_FCMD, WR_QPP | SECT_4K}, + {"N25Q64A", 0x20bb17, 0x0, 64 * 1024, 128, RD_FCMD, WR_QPP | SECT_4K}, + {"N25Q128", 0x20ba18, 0x0, 64 * 1024, 256, RD_FCMD, WR_QPP}, + {"N25Q128A", 0x20bb18, 0x0, 64 * 1024, 256, RD_FCMD, WR_QPP}, + {"N25Q256", 0x20ba19, 0x0, 64 * 1024, 512, RD_FCMD, WR_QPP | SECT_4K}, + {"N25Q256A", 0x20bb19, 0x0, 64 * 1024, 512, RD_FCMD, WR_QPP | SECT_4K}, + {"N25Q512", 0x20ba20, 0x0, 64 * 1024, 1024, RD_FCMD, WR_QPP | E_FSR | SECT_4K}, + {"N25Q512A", 0x20bb20, 0x0, 64 * 1024, 1024, RD_FCMD, WR_QPP | E_FSR | SECT_4K}, + {"N25Q1024", 0x20ba21, 0x0, 64 * 1024, 2048, RD_FCMD, WR_QPP | E_FSR | SECT_4K}, + {"N25Q1024A", 0x20bb21, 0x0, 64 * 1024, 2048, RD_FCMD, WR_QPP | E_FSR | SECT_4K}, #endif #ifdef CONFIG_SPI_FLASH_SST /* SST */ {"SST25VF040B", 0xbf258d, 0x0, 64 * 1024, 8, RD_NORM, SECT_4K | SST_WR},
drivers/mtd/spi/sf_probe.c +18 -1
@@ -26,6 +26,7 @@static int spi_flash_probe_slave (struct spi_flash *flash) {struct spi_slave *spi = flash->spi; +u8 mode_rx, e_rd_cmd;int ret;/* Setup spi_slave */
@@ -34,6 +35,22 @@ static int spi_flash_probe_slave(struct spi_flash *flash)return -ENODEV ; } +/* Convert SPI mode_rx and mode to SPI flash read commands */ + mode_rx = spi->mode_rx; +if (mode_rx &SPI_RX_QUAD ) { + e_rd_cmd =RD_NORM |QUAD_OUTPUT_FAST ; +if (spi->mode &SPI_TX_QUAD ) + e_rd_cmd |=QUAD_IO_FAST ; + }else if (mode_rx &SPI_RX_DUAL ) { + e_rd_cmd =RD_NORM |DUAL_OUTPUT_FAST ; +if (spi->mode &SPI_TX_DUAL ) + e_rd_cmd |=DUAL_IO_FAST ; + }else if ((mode_rx & (SPI_RX_SLOW |SPI_RX_FAST )) ==SPI_RX_SLOW ) { + e_rd_cmd =ARRAY_SLOW ; + }else { + e_rd_cmd =RD_NORM ; + } +/* Claim spi bus */ ret =spi_claim_bus (spi);if (ret) {
@@ -41,7 +58,7 @@ static int spi_flash_probe_slave(struct spi_flash *flash)return ret; } - ret =spi_flash_scan (flash); + ret =spi_flash_scan (flash, e_rd_cmd);if (ret) goto err_read_id;
drivers/mtd/spi/spi_flash.c +6 -3
@@ -987,7 +987,7 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) }#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ -int spi_flash_scan (struct spi_flash *flash) +int spi_flash_scan (struct spi_flash *flash,u8 e_rd_cmd) {struct spi_slave *spi = flash->spi;const struct spi_flash_params *params;
@@ -1000,7 +1000,10 @@ int spi_flash_scan(struct spi_flash *flash)CMD_READ_DUAL_OUTPUT_FAST ,CMD_READ_QUAD_OUTPUT_FAST ,CMD_READ_DUAL_IO_FAST , - CMD_READ_QUAD_IO_FAST }; +CMD_READ_QUAD_IO_FAST , +CMD_READ_DUAL_IO_FAST ,/* same op code as for DUAL_IO_FAST */ + CMD_READ_QUAD_IO_FAST, /* same op code as for QUAD_IO_FAST */ + };/* Assign spi_flash ops */ #ifndef CONFIG_DM_SPI_FLASH
@@ -1115,7 +1118,7 @@ int spi_flash_scan(struct spi_flash *flash) flash->sector_size = flash->erase_size;/* Look for the fastest read cmd */ - cmd =fls (params->e_rd_cmd & spi->mode_rx); + cmd =fls (params->e_rd_cmd & e_rd_cmd);if (cmd) { cmd = spi_read_cmds_array[cmd -1 ]; flash->read_cmd = cmd;
Signature · 1 line
1.8.2.2
PATCH 12/18 sf: fix detection of QSPI memories when they boot in Quad or Dual mode
In reply to Cyrille PitchenThe quad (or dual) mode of a SPI flash memory may be enabled at boot time by non-volatile bits in some setting register. Also such a mode may have already been enabled at early stage by some boot loader.
Hence, we should not guess the SPI flash memory is always configured for the regular SPI 1-1-1 protocol.
Micron and Macronix memories, once their Quad (or dual for Micron) mode enabled, no longer process the regular JEDEC Read ID (0x9f) command but instead reply to a new command: JEDEC Read ID Multiple I/O (0xaf). Besides, in Quad mode both memory manufacturers expect ALL commands to use the SPI 4-4-4 protocol. For Micron memories, enabling their Dual mode implies to use the SPI 2-2-2 protocol for ALL commands.
Winbond memories, once their Quad mode enabled, expect ALL commands to use the SPI 4-4-4 protocol. Unlike Micron and Macronix memories, they still reply to the regular JEDEC Read ID (0x9f) command but not the JEDEC Read ID Multiple I/O (0x9f) command.
--- drivers/mtd/spi/sf_internal.h | 1 + drivers/mtd/spi/spi_flash.c | 90 +++++++++++++++++++++++++++++++++---------- include/spi_flash.h | 45 ++++++++++++++++++++++ 3 files changed, 116 insertions(+), 20 deletions(-)
drivers/mtd/spi/sf_internal.h +1 -0
@@ -99,6 +99,7 @@ enum spi_nor_option_flags {#define CMD_READ_STATUS1 0x35#define CMD_READ_CONFIG 0x35#define CMD_FLAG_STATUS 0x70 +#define CMD_READ_ID_MIO 0xaf/* Bank addr access commands */ #ifdef CONFIG_SPI_FLASH_BAR
drivers/mtd/spi/spi_flash.c +70 -20
112 lines not on this page · raw message
include/spi_flash.h +45 -0
63 lines not on this page · raw message
Signature · 1 line
1.8.2.2
PATCH 13/18 sf: add helper function to set the number of dummy bytes
In reply to Cyrille PitchenThis patch adds a helper function to ease the conversion between a number of dummy clock cycles and number of bytes.
Actually this number of bytes depends on both the number of dummy clock cycles and SPI protocol used by (Fast) Read commands.
This new function is exported so it can be used by other drivers.
--- drivers/mtd/spi/sf_internal.h | 6 ++++++ drivers/mtd/spi/spi_flash.c | 11 +++++++++++ 2 files changed, 17 insertions(+)
drivers/mtd/spi/sf_internal.h +6 -0
@@ -240,6 +240,12 @@ typedef int (*spi_flash_read_fn)(struct spi_flash *, u32, size_t, void *);int spi_flash_read_alg (struct spi_flash *flash,u32 offset,size_t len,void *data,spi_flash_read_fn read_fn); +/* +* Helper function to compute the number of dummy bytes from both the number +* of dummy cycles and the SPI protocol used for (Fast) Read operations. +*/ +int spi_flash_set_dummy_byte (struct spi_flash *flash,u8 num_dummy_cycles); +#ifdef CONFIG_SPI_FLASH_MTD int spi_flash_mtd_register (struct spi_flash *flash);void spi_flash_mtd_unregister (void );
drivers/mtd/spi/spi_flash.c +11 -0
@@ -882,6 +882,17 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) }#endif +int spi_flash_set_dummy_byte (struct spi_flash *flash,u8 num_dummy_cycles) +{ +u8 dummy_bits = num_dummy_cycles; + + dummy_bits *=SPI_FLASH_PROTO_ADR_FROM_PROTO (flash->read_proto); +if (dummy_bits &0x7 ) +return -EINVAL ; + + flash->dummy_byte = dummy_bits >>3 ; +return 0 ; +}#ifdef CONFIG_SPI_FLASH_MACRONIX static int macronix_quad_enable (struct spi_flash *flash)
Signature · 1 line
1.8.2.2
PATCH 14/18 sf: add 4byte address opcodes
In reply to Cyrille PitchenThis patch provides an alternative to support memory >16MiB (>128Mib). Indeed using the Base Address Register changes the internal state of the SPI flash memory. However some early boot loaders expect to access the first memory bank of the SPI flash. Then when another bank has been selected, those boot loader will fail to read the right data.
Using 4byte address opcodes doesn't change the internal state of the SPI flash memory but sill allows to access data above 16MiB.
--- drivers/mtd/spi/Kconfig | 18 ++++++++- drivers/mtd/spi/sf_internal.h | 17 +++++++- drivers/mtd/spi/spi_flash.c | 93 +++++++++++++++++++++++++++++++++++++------ include/spi_flash.h | 2 + 4 files changed, 114 insertions(+), 16 deletions(-)
drivers/mtd/spi/Kconfig +17 -1
@@ -34,14 +34,30 @@ config SPI_FLASH If unsure, say N +config SPI_FLASH_ABOVE_16MB + bool "Support of >16MB memories" + depends on SPI_FLASH + default n + +choice + prompt "Select >16MB method" + depends on SPI_FLASH_ABOVE_16MB + config SPI_FLASH_BAR bool "SPI flash Bank/Extended address register support" - depends on SPI_FLASH help Enable the SPI flash Bank/Extended address register support. Bank/Extended address registers are used to access the flash which has size > 16MiB in 3-byte addressing. +config SPI_FLASH_4B_OPCODES + bool "4-byte address op codes support" + help + Replace regular 3-byte address op codes by thier 4-byte address + version when the size of the memory if greater than 16MB. + +endchoice + if SPI_FLASH config SPI_FLASH_ATMEL
drivers/mtd/spi/sf_internal.h +15 -2
@@ -62,8 +62,8 @@ enum spi_nor_option_flags { SNOR_F_USE_FSR = BIT(2), }; -#define SPI_FLASH_3B_ADDR_LEN 3 -#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) +#define SPI_FLASH_4B_ADDR_LEN 4 +#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_4B_ADDR_LEN)#define SPI_FLASH_16MB_BOUN 0x1000000/* CFI Manufacture ID's */
@@ -79,6 +79,9 @@ enum spi_nor_option_flags {#define CMD_ERASE_32K 0x52#define CMD_ERASE_CHIP 0xc7#define CMD_ERASE_64K 0xd8 +#define CMD_ERASE_4K_4B 0x21 +#define CMD_ERASE_32K_4B 0x5c +#define CMD_ERASE_64K_4B 0xdc/* Write commands */ #define CMD_WRITE_STATUS 0x01
@@ -86,6 +89,10 @@ enum spi_nor_option_flags {#define CMD_WRITE_DISABLE 0x04#define CMD_WRITE_ENABLE 0x06#define CMD_QUAD_PAGE_PROGRAM 0x32 +#define CMD_QUAD_PAGE_PROGRAM_MXIC 0x38 +#define CMD_PAGE_PROGRAM_4B 0x12 +#define CMD_QUAD_PAGE_PROGRAM_4B 0x34 +#define CMD_QUAD_PAGE_PROGRAM_MXIC_4B 0x3e/* Read commands */ #define CMD_READ_ARRAY_SLOW 0x03
@@ -94,6 +101,12 @@ enum spi_nor_option_flags {#define CMD_READ_DUAL_IO_FAST 0xbb#define CMD_READ_QUAD_OUTPUT_FAST 0x6b#define CMD_READ_QUAD_IO_FAST 0xeb +#define CMD_READ_ARRAY_SLOW_4B 0x13 +#define CMD_READ_ARRAY_FAST_4B 0x0c +#define CMD_READ_DUAL_OUTPUT_FAST_4B 0x3c +#define CMD_READ_DUAL_IO_FAST_4B 0xbc +#define CMD_READ_QUAD_OUTPUT_FAST_4B 0x6c +#define CMD_READ_QUAD_IO_FAST_4B 0xec#define CMD_READ_ID 0x9f#define CMD_READ_STATUS 0x05#define CMD_READ_STATUS1 0x35
drivers/mtd/spi/spi_flash.c +80 -13
147 lines not on this page · raw message
include/spi_flash.h +2 -0
@@ -88,6 +88,7 @@ enum spi_flash_protocol {* @read_proto SPI protocol to be used by &read ops * @write_proto SPI protocol to be used by &write ops * @erase_proto SPI protocol to be used by &erase ops +* @addr_width Number of address bytes (typically 3 or 4) * @memory_map: Address of read-only SPI flash access * @flash_lock: lock a region of the SPI Flash * @flash_unlock: unlock a region of the SPI Flash
@@ -117,6 +118,7 @@ struct spi_flash {u32 page_size;u32 sector_size;u32 erase_size; +u32 addr_width;#ifdef CONFIG_SPI_FLASH_BAR u8 bank_read_cmd;u8 bank_write_cmd;
Signature · 1 line
1.8.2.2
PATCH v2 14/18 sf: add 4byte address opcodes
This patch provides an alternative to support memory >16MiB (>128Mib). Indeed using the Base Address Register changes the internal state of the SPI flash memory. However some early boot loaders expect to access the first memory bank of the SPI flash. Then when another bank has been selected, those boot loader will fail to read the right data.
Using 4byte address opcodes doesn't change the internal state of the SPI flash memory but sill allows to access data above 16MiB.
---
ChangeLog:
v1 -> v2:
- add missing entry for PAGE PROGRAM op code
drivers/mtd/spi/Kconfig | 18 ++++++++- drivers/mtd/spi/sf_internal.h | 17 +++++++- drivers/mtd/spi/spi_flash.c | 94 +++++++++++++++++++++++++++++++++++++------ include/spi_flash.h | 2 + 4 files changed, 115 insertions(+), 16 deletions(-)
drivers/mtd/spi/Kconfig +17 -1
@@ -34,14 +34,30 @@ config SPI_FLASH If unsure, say N +config SPI_FLASH_ABOVE_16MB + bool "Support of >16MB memories" + depends on SPI_FLASH + default n + +choice + prompt "Select >16MB method" + depends on SPI_FLASH_ABOVE_16MB + config SPI_FLASH_BAR bool "SPI flash Bank/Extended address register support" - depends on SPI_FLASH help Enable the SPI flash Bank/Extended address register support. Bank/Extended address registers are used to access the flash which has size > 16MiB in 3-byte addressing. +config SPI_FLASH_4B_OPCODES + bool "4-byte address op codes support" + help + Replace regular 3-byte address op codes by thier 4-byte address + version when the size of the memory if greater than 16MB. + +endchoice + if SPI_FLASH config SPI_FLASH_ATMEL
drivers/mtd/spi/sf_internal.h +15 -2
@@ -62,8 +62,8 @@ enum spi_nor_option_flags { SNOR_F_USE_FSR = BIT(2), }; -#define SPI_FLASH_3B_ADDR_LEN 3 -#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) +#define SPI_FLASH_4B_ADDR_LEN 4 +#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_4B_ADDR_LEN)#define SPI_FLASH_16MB_BOUN 0x1000000/* CFI Manufacture ID's */
@@ -79,6 +79,9 @@ enum spi_nor_option_flags {#define CMD_ERASE_32K 0x52#define CMD_ERASE_CHIP 0xc7#define CMD_ERASE_64K 0xd8 +#define CMD_ERASE_4K_4B 0x21 +#define CMD_ERASE_32K_4B 0x5c +#define CMD_ERASE_64K_4B 0xdc/* Write commands */ #define CMD_WRITE_STATUS 0x01
@@ -86,6 +89,10 @@ enum spi_nor_option_flags {#define CMD_WRITE_DISABLE 0x04#define CMD_WRITE_ENABLE 0x06#define CMD_QUAD_PAGE_PROGRAM 0x32 +#define CMD_QUAD_PAGE_PROGRAM_MXIC 0x38 +#define CMD_PAGE_PROGRAM_4B 0x12 +#define CMD_QUAD_PAGE_PROGRAM_4B 0x34 +#define CMD_QUAD_PAGE_PROGRAM_MXIC_4B 0x3e/* Read commands */ #define CMD_READ_ARRAY_SLOW 0x03
@@ -94,6 +101,12 @@ enum spi_nor_option_flags {#define CMD_READ_DUAL_IO_FAST 0xbb#define CMD_READ_QUAD_OUTPUT_FAST 0x6b#define CMD_READ_QUAD_IO_FAST 0xeb +#define CMD_READ_ARRAY_SLOW_4B 0x13 +#define CMD_READ_ARRAY_FAST_4B 0x0c +#define CMD_READ_DUAL_OUTPUT_FAST_4B 0x3c +#define CMD_READ_DUAL_IO_FAST_4B 0xbc +#define CMD_READ_QUAD_OUTPUT_FAST_4B 0x6c +#define CMD_READ_QUAD_IO_FAST_4B 0xec#define CMD_READ_ID 0x9f#define CMD_READ_STATUS 0x05#define CMD_READ_STATUS1 0x35
drivers/mtd/spi/spi_flash.c +81 -13
148 lines not on this page · raw message
include/spi_flash.h +2 -0
@@ -88,6 +88,7 @@ enum spi_flash_protocol {* @read_proto SPI protocol to be used by &read ops * @write_proto SPI protocol to be used by &write ops * @erase_proto SPI protocol to be used by &erase ops +* @addr_width Number of address bytes (typically 3 or 4) * @memory_map: Address of read-only SPI flash access * @flash_lock: lock a region of the SPI Flash * @flash_unlock: unlock a region of the SPI Flash
@@ -117,6 +118,7 @@ struct spi_flash {u32 page_size;u32 sector_size;u32 erase_size; +u32 addr_width;#ifdef CONFIG_SPI_FLASH_BAR u8 bank_read_cmd;u8 bank_write_cmd;
Signature · 1 line
1.8.2.2
PATCH 15/18 sf: prepare next fixes to support of QSPI memories by manufacturer
In reply to Cyrille PitchenThis is just a transitional patch to add manufacturer dedicated support for QSPI memories.
Indeed, using Quad SPI protocols is slighty more complicated than simply enabling the Quad I/O or QPI mode. We should also take care about the number of dummy cycles. For instance, some Spansion QSPI memories use a factory default value of 6 dummy cycles.
Besides we have to care about the mode cycles: special kind of dummy cycles which make the SPI flash memory enter/leaver its Continuous Read/ Enhanced Performance mode. This mode is actually used by XIP operations but not relevant in the MTD layer. However we should prevent the SPI flash memory from entering Continuous Read mode by mistake. Depending on the manufacturer, it can be done by using the right Fast Read op code (Winbond) or by updating a dedicated bit in one configuration register (Micron).
Also the QSPI manufacturers don't support the exact same SPI protocols for Fast Read operations. We need to provide a mean to tune SPI protocols and the op codes by manufacturer.
For all these reasons, future patches are to come to add QSPI support by manufacturer. Till then, the legacy code is still used as a fallback implementation.
--- drivers/mtd/spi/spi_flash.c | 155 ++++++++++++++++++++++++++++---------------- 1 file changed, 99 insertions(+), 56 deletions(-)
drivers/mtd/spi/spi_flash.c +99 -56
@@ -1033,6 +1033,98 @@ static int set_quad_mode(struct spi_flash *flash, u8 idcode0) } } +/* Transitional function to be removed */ +static int spi_flash_setup_deprecated (struct spi_flash *flash, +const struct spi_flash_params *params, +int best_match) +{ +struct spi_slave *spi = flash->spi; +u8 idcode0 = params->jedec >>16 ; +u8 cmd; +int ret; +static u8 spi_read_cmds_array[] = { +CMD_READ_ARRAY_SLOW , +CMD_READ_ARRAY_FAST , +CMD_READ_DUAL_OUTPUT_FAST , +CMD_READ_QUAD_OUTPUT_FAST , +CMD_READ_DUAL_IO_FAST , +CMD_READ_QUAD_IO_FAST , +CMD_READ_DUAL_IO_FAST ,/* same op code as for DUAL_IO_FAST */ +CMD_READ_QUAD_IO_FAST ,/* same op code as for QUAD_IO_FAST */ + }; + +/* Look for the fastest read cmd */ +if (best_match) { + cmd = spi_read_cmds_array[best_match -1 ]; + flash->read_cmd = cmd; + }else { +/* Go for default supported read cmd */ + flash->read_cmd =CMD_READ_ARRAY_FAST ; + } + +/* Not require to look for fastest only two write cmds yet */ +if (params->flags &WR_QPP && spi->mode &SPI_TX_QUAD ) + flash->write_cmd =CMD_QUAD_PAGE_PROGRAM ; +else +/* Go for default supported write cmd */ + flash->write_cmd =CMD_PAGE_PROGRAM ; + +/* Set the quad enable bit - only for quad commands */ +if ((flash->read_cmd ==CMD_READ_QUAD_OUTPUT_FAST ) || + (flash->read_cmd ==CMD_READ_QUAD_IO_FAST ) || + (flash->write_cmd ==CMD_QUAD_PAGE_PROGRAM )) { + ret =set_quad_mode (flash, idcode0); +if (ret) { +debug ("SF: Fail to set QEB for %02x\n" , idcode0); +return -EINVAL ; + } + } + +/* Read dummy_byte: dummy byte is determined based on the +* dummy cycles of a particular command. +* Fast commands - dummy_byte = dummy_cycles/8 +* I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8 +* For I/O commands except cmd[0] everything goes on no.of lines +* based on particular command but incase of fast commands except +* data all go on single line irrespective of command. +*/ +switch (flash->read_cmd) { +case CMD_READ_QUAD_IO_FAST : + flash->dummy_byte =2 ; +break ; +case CMD_READ_ARRAY_SLOW : + flash->dummy_byte =0 ; +break ; +default : + flash->dummy_byte =1 ; + } + +return 0 ; +} + +static int spi_flash_setup (struct spi_flash *flash, +const struct spi_flash_params *params, +u8 e_rd_cmd) +{ +int match =fls (params->e_rd_cmd & e_rd_cmd); + +/* +* The (Fast) Read and Page Program opcodes to be used depends on the +* manufacturer. +*/ +switch (params->jedec >>16 ) { +/* +* TODO: Manufacturer dedicated setup will be added HERE by +* further patches. +*/ + +default : +return spi_flash_setup_deprecated (flash, params, match); + } + +return 0 ; +} +#if CONFIG_IS_ENABLED (OF_CONTROL )int spi_flash_decode_fdt (const void *blob,struct spi_flash *flash) {
@@ -1090,18 +1182,8 @@ int spi_flash_scan(struct spi_flash *flash, u8 e_rd_cmd)const struct spi_flash_params *params;const struct spi_flash_read_id_config *cfg;u16 jedec, ext_jedec; -u8 cmd, idcode[5 ]; +u8 idcode[5 ];int ret; -static u8 spi_read_cmds_array[] = { -CMD_READ_ARRAY_SLOW , -CMD_READ_ARRAY_FAST , -CMD_READ_DUAL_OUTPUT_FAST , -CMD_READ_QUAD_OUTPUT_FAST , -CMD_READ_DUAL_IO_FAST , -CMD_READ_QUAD_IO_FAST , -CMD_READ_DUAL_IO_FAST ,/* same op code as for DUAL_IO_FAST */ -CMD_READ_QUAD_IO_FAST ,/* same op code as for QUAD_IO_FAST */ - };/* Assign spi_flash ops */ #ifndef CONFIG_DM_SPI_FLASH
@@ -1238,52 +1320,13 @@ int spi_flash_scan(struct spi_flash *flash, u8 e_rd_cmd)/* Now erase size becomes valid sector size */ flash->sector_size = flash->erase_size; -/* Look for the fastest read cmd */ - cmd =fls (params->e_rd_cmd & e_rd_cmd); -if (cmd) { - cmd = spi_read_cmds_array[cmd -1 ]; - flash->read_cmd = cmd; - }else { -/* Go for default supported read cmd */ - flash->read_cmd =CMD_READ_ARRAY_FAST ; - } - -/* Not require to look for fastest only two write cmds yet */ -if (params->flags &WR_QPP && spi->mode &SPI_TX_QUAD ) - flash->write_cmd =CMD_QUAD_PAGE_PROGRAM ; -else -/* Go for default supported write cmd */ - flash->write_cmd =CMD_PAGE_PROGRAM ; - -/* Set the quad enable bit - only for quad commands */ -if ((flash->read_cmd ==CMD_READ_QUAD_OUTPUT_FAST ) || - (flash->read_cmd ==CMD_READ_QUAD_IO_FAST ) || - (flash->write_cmd ==CMD_QUAD_PAGE_PROGRAM )) { - ret =set_quad_mode (flash, idcode[0 ]); -if (ret) { -debug ("SF: Fail to set QEB for %02x\n" , idcode[0 ]); -return -EINVAL ; - } - } - -/* Read dummy_byte: dummy byte is determined based on the -* dummy cycles of a particular command. -* Fast commands - dummy_byte = dummy_cycles/8 -* I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8 -* For I/O commands except cmd[0] everything goes on no.of lines -* based on particular command but incase of fast commands except -* data all go on single line irrespective of command. +/* +* Setup (Fast) Read & Page Program opcode and protocols. +* Also set the right number of dummy/mode cycles. */ -switch (flash->read_cmd) { -case CMD_READ_QUAD_IO_FAST : - flash->dummy_byte =2 ; -break ; -case CMD_READ_ARRAY_SLOW : - flash->dummy_byte =0 ; -break ; -default : - flash->dummy_byte =1 ; - } + ret =spi_flash_setup (flash, params, e_rd_cmd); +if (ret <0 ) +return ret;#ifdef CONFIG_SPI_FLASH_STMICRO if (params->flags &E_FSR )
Signature · 1 line
1.8.2.2
PATCH 16/18 sf: fix support of Micron memories
In reply to Cyrille PitchenThis patch provides support of Micron QSPI memories.
--- drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/sf_internal.h | 24 +++++ drivers/mtd/spi/sf_micron.c | 222 ++++++++++++++++++++++++++++++++++++++++++ drivers/mtd/spi/spi_flash.c | 13 +-- 4 files changed, 251 insertions(+), 9 deletions(-) create mode 100644 drivers/mtd/spi/sf_micron.c
drivers/mtd/spi/Makefile +1 -0
@@ -13,6 +13,7 @@ obj-$(CONFIG_SPL_SPI_BOOT) += fsl_espi_spl.o endif obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o sf_params.o sf.o +obj-$(CONFIG_SPI_FLASH_STMICRO) += sf_micron.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
drivers/mtd/spi/sf_internal.h +24 -0
@@ -142,6 +142,24 @@ enum spi_nor_option_flags {# define CMD_SST_AAI_WP 0xAD/* Auto Address Incr Word Program */ #endif +/* Micron specific */ +#ifdef CONFIG_SPI_FLASH_STMICRO + +/* Volatile Configuration Register (VCR) */ +#define CMD_MICRON_WR_VCR 0x81 +#define CMD_MICRON_RD_VCR 0x85 +#define MICRON_VCR_XIP BIT(3) +#define MICRON_VCR_DUMMIES 0xf0 +#define MICRON_VCR_DUMMIES_ (x) (((x) << 4) & MICRON_VCR_DUMMIES) + +/* Enhanced Volatile Configuraiton Register (EVCR) */ +#define CMD_MICRON_WR_EVCR 0x61 +#define CMD_MICRON_RD_EVCR 0x65 +#define MICRON_EVCR_QUAD_DIS BIT(7) +#define MICRON_EVCR_DUAL_DIS BIT(6) +#endif + +/** * struct spi_flash_params - SPI/QSPI flash device params structure *
@@ -264,6 +282,12 @@ int spi_flash_mtd_register(struct spi_flash *flash);void spi_flash_mtd_unregister (void );#endif +#ifdef CONFIG_SPI_FLASH_STMICRO +int spi_flash_setup_micron (struct spi_flash *flash, +const struct spi_flash_params *params, +int best_match); +#endif +/** * spi_flash_scan - scan the SPI FLASH * @flash: the spi flash structure
drivers/mtd/spi/sf_micron.c new file +222 -0
222 lines not on this page · raw message
drivers/mtd/spi/spi_flash.c +4 -9
@@ -1022,11 +1022,6 @@ static int set_quad_mode(struct spi_flash *flash, u8 idcode0)case SPI_FLASH_CFI_MFR_WINBOND :return spansion_quad_enable (flash);#endif -#ifdef CONFIG_SPI_FLASH_STMICRO -case SPI_FLASH_CFI_MFR_STMICRO : -debug ("SF: QEB is volatile for %02x flash\n" , idcode0); -return 0 ; -#endif default :printf ("SF: Need set QEB func for %02x flash\n" , idcode0);return -1 ;
@@ -1113,10 +1108,10 @@ static int spi_flash_setup(struct spi_flash *flash,* manufacturer. */ switch (params->jedec >>16 ) { -/* -* TODO: Manufacturer dedicated setup will be added HERE by -* further patches. -*/ +#ifdef CONFIG_SPI_FLASH_STMICRO +case SPI_FLASH_CFI_MFR_STMICRO : +return spi_flash_setup_micron (flash, params, match); +#endif default :return spi_flash_setup_deprecated (flash, params, match);
Signature · 1 line
1.8.2.2
PATCH 17/18 ARM: at91: clock: add function to get QSPI clocks
In reply to Cyrille PitchenAdd the new get_qpsi_clk_rate() function which will be needed by the future Atmel QSPI controller driver.
--- arch/arm/mach-at91/include/mach/clk.h | 5 +++++ 1 file changed, 5 insertions(+)
arch/arm/mach-at91/include/mach/clk.h +5 -0
@@ -99,6 +99,11 @@ static inline unsigned long get_spi_clk_rate(unsigned int dev_id)return get_mck_clk_rate (); } +static inline unsigned long get_qspi_clk_rate (unsigned int dev_id) +{ +return get_mck_clk_rate (); +} +static inline unsigned long get_twi_clk_rate (unsigned int dev_id) {if (get_h32mxdiv ())
Signature · 1 line
1.8.2.2
PATCH 18/18 sf: add driver for Atmel QSPI controller
In reply to Cyrille PitchenThis patch adds support of the Atmel QSPI controller.
--- drivers/mtd/spi/Makefile | 1 + drivers/mtd/spi/atmel_qspi_flash.c | 432 +++++++++++++++++++++++++++++++++++++ drivers/spi/Kconfig | 9 + drivers/spi/Makefile | 1 + drivers/spi/atmel_qspi.c | 150 +++++++++++++ drivers/spi/atmel_qspi.h | 145 +++++++++++++ 6 files changed, 738 insertions(+) create mode 100644 drivers/mtd/spi/atmel_qspi_flash.c create mode 100644 drivers/spi/atmel_qspi.c create mode 100644 drivers/spi/atmel_qspi.h
drivers/mtd/spi/Makefile +1 -0
@@ -17,3 +17,4 @@ obj-$(CONFIG_SPI_FLASH_STMICRO) += sf_micron.o obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o +obj-$(CONFIG_ATMEL_QSPI) += atmel_qspi_flash.o
drivers/mtd/spi/atmel_qspi_flash.c new file +432 -0
432 lines not on this page · raw message
drivers/spi/Kconfig +9 -0
@@ -23,6 +23,15 @@ config ALTERA_SPI IP core. Please find details on the "Embedded Peripherals IP User Guide" of Altera. +config ATMEL_QSPI + bool "Atmel QSPI driver" + depends on ARCH_AT91 + select SPI_FLASH + select DM_SPI_FLASH + help + Enable the Ateml Quad-SPI (QSPI) driver. This driver can only be + used to access SPI NOR flashes. + config CADENCE_QSPI bool "Cadence QSPI driver" help
drivers/spi/Makefile +1 -0
@@ -18,6 +18,7 @@ endif obj-$(CONFIG_ALTERA_SPI) += altera_spi.o obj-$(CONFIG_ARMADA100_SPI) += armada100_spi.o obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o +obj-$(CONFIG_ATMEL_QSPI) += atmel_qspi.o obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o obj-$(CONFIG_BFIN_SPI) += bfin_spi.o obj-$(CONFIG_BFIN_SPI6XX) += bfin_spi6xx.o
drivers/spi/atmel_qspi.c new file +150 -0
150 lines not on this page · raw message
drivers/spi/atmel_qspi.h new file +145 -0
145 lines not on this page · raw message
Signature · 1 line
1.8.2.2
cover sf: fix support of QSPI memories and controllers
In reply to Cyrille PitchenQuoted 26 lines · Cyrille Pitchen
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a memory.
Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()
Quoted 8 lines
sf: fix selection of supported READ commands for QSPI memories
sf: fix detection of QSPI memories when they boot in Quad or Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controller
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1]
http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-next
cover sf: fix support of QSPI memories and controllers
Quoted 36 lines · Jagan Teki
Quoted 26 lines · Cyrille Pitchen
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a memory.
Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()Quoted 8 lines
sf: fix selection of supported READ commands for QSPI memories
sf: fix detection of QSPI memories when they boot in Quad or Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controller
Quoted 6 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1]
http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-next
The patchset seems to be in a sensible shape to me, so maybe we should do it the other way around -- get this in and have you rebase your V6(?) patchset on top of it -- since clearly your patchset will take some more time to ripe.
Signature · 2 lines
Best regards, Marek Vasut
cover sf: fix support of QSPI memories and controllers
In reply to Jagan TekiLe 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 36 lines · Cyrille Pitchen
Quoted 26 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a memory.
Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()Quoted 8 lines
sf: fix selection of supported READ commands for QSPI memories
sf: fix detection of QSPI memories when they boot in Quad or Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controller
Quoted 4 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1] http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-next
Hi Jagan,
I've started to have a look on your branch. I hope it's not to late for few comments:
Globally I see the new code attend to match the spi-nor framework from Linux. OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.
First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit to add support to Micron QSPI memories was reverted since it didn't work alone. In his reply, Brian agreed the code was not tested and should not have been merged.
This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol change at the QSPI memory side. This applies to Micron memories when they enter their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the struct spi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the .read_mmap() also.
- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.
(Q)SPI controller drivers cannot guess the protocol to be used from the command op code. Indeed, taking the Micron case as un example, the very same 0xeb op code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or with the SPI 4-4-4 protocol (Micron Quad I/O mode).
Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles (if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)
So the SNOR_OP_READ_1_1_2_IO macro for the Fast Read Dual I/O command (as opposed to the macro SNOR_OP_READ_1_1_2 macro for the Fast Read Dual Output command) doesn't make sense: it should be named SNOR_OP_READ_1_2_2.
Then about the value used for the dummy cycles, it's not always true that we don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to during Fast Read operations to make the memory enter/leaver its Continuous Read mode. Once is Continuous Read mode, the op code byte is no longer sent, it is implicit and the command actually starts from the address cycles. This mode is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by updating the relevant bit in some configuration register (e.g. setting the XIP bit in Micron Volatile Configuration Register) or by choosing the right op code (e.g. for Winbond memories in QPI mode, both the 0x0b and 0xeb op codes can be used for Fast Read 4-4-4 operation but only the 0xeb op code cares about the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.
Besides when sending a regular JEDEC Read ID (0x9f) command to probe the (Q)SPI memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not already enabled. This not always true, some early bootloarders, such as the sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from the QSPI memory. If so, the QSPI memory no longer replies to the 0x9f command in SPI 1-1-1 protocol but instead to the 0xaf command in SPI 4-4-4 protocol.
Finally, about the proper way to describe the SPI controller capabilities, the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4 protocols. Maybe some SPI controllers support the first protocol but not the latest. It could be good to add another argument to spi_nor_scan() providing an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI memory and select the proper protocol, this new argument should use the same range of values as the .flash_read field in the struct spi_nor_info used to describe the SPI memories.
For backward compatibility, the m25p80 driver could then convert the SPI modes into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related to spi_flash_probe_slave() in sf_probe.c:
/* Convert SPI mode_rx and mode to SPI flash read commands */
+ mode_rx = spi->mode_rx;
+ if (mode_rx & SPI_RX_QUAD) {
+ e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST;
+ if (spi->mode & SPI_TX_QUAD)
+ e_rd_cmd |= QUAD_IO_FAST;
+ } else if (mode_rx & SPI_RX_DUAL) {
+ e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST;
+ if (spi->mode & SPI_TX_DUAL)
+ e_rd_cmd |= DUAL_IO_FAST;
+ } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) {
+ e_rd_cmd = ARRAY_SLOW;
+ } else {
+ e_rd_cmd = RD_NORM;
+ }
+
[...]
- ret = spi_flash_scan(flash);
+ ret = spi_flash_scan(flash, e_rd_cmd);
I've spent a lot of time working on the QSPI memory topic so I can tell you that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support, please let me know.
Best regards,
Cyrille
[1] http://lists.infradead.org/pipermail/linux-mtd/2016-February/065371.html
cover sf: fix support of QSPI memories and controllers
Quoted 151 lines · Cyrille Pitchen
Le 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 36 lines · Cyrille Pitchen
Quoted 26 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a memory.
Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()Quoted 8 lines
sf: fix selection of supported READ commands for QSPI memories
sf: fix detection of QSPI memories when they boot in Quad or Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controllerQuoted 4 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1] http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-next
Hi Jagan,
I've started to have a look on your branch. I hope it's not to late for few comments:
Globally I see the new code attend to match the spi-nor framework from Linux. OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.
First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit to add support to Micron QSPI memories was reverted since it didn't work alone. In his reply, Brian agreed the code was not tested and should not have been merged.
This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol change at the QSPI memory side. This applies to Micron memories when they enter their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the structspi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the .read_mmap() also.
- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.(Q)SPI controller drivers cannot guess the protocol to be used from the command op code. Indeed, taking the Micron case as un example, the very same
0xebop code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or with the SPI 4-4-4 protocol (Micron Quad I/O mode).Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles (if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)So the
SNOR_OP_READ_1_1_2_IOmacro for the Fast Read Dual I/O command (as opposed to the macroSNOR_OP_READ_1_1_2macro for the Fast Read Dual Output command) doesn't make sense: it should be namedSNOR_OP_READ_1_2_2.Then about the value used for the dummy cycles, it's not always true that we don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to during Fast Read operations to make the memory enter/leaver its Continuous Read mode. Once is Continuous Read mode, the op code byte is no longer sent, it is implicit and the command actually starts from the address cycles. This mode is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by updating the relevant bit in some configuration register (e.g. setting the XIP bit in Micron Volatile Configuration Register) or by choosing the right op code (e.g. for Winbond memories in QPI mode, both the
0x0band0xebop codes can be used for Fast Read 4-4-4 operation but only the0xebop code cares about the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.Besides when sending a regular JEDEC Read ID (
0x9f) command to probe the (Q)SPI memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not already enabled. This not always true, some early bootloarders, such as the sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from the QSPI memory. If so, the QSPI memory no longer replies to the0x9fcommand in SPI 1-1-1 protocol but instead to the0xafcommand in SPI 4-4-4 protocol.Finally, about the proper way to describe the SPI controller capabilities, the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4 protocols. Maybe some SPI controllers support the first protocol but not the latest. It could be good to add another argument tospi_nor_scan()providing an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI memory and select the proper protocol, this new argument should use the same range of values as the .flash_read field in the structspi_nor_infoused to describe the SPI memories.For backward compatibility, the m25p80 driver could then convert the SPI modes into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related to
spi_flash_probe_slave()insf_probe.c:/* Convert SPI mode_rx and mode to SPI flash read commands */(quoted diff) +16
-1+ mode_rx = spi->mode_rx; + if (mode_rx & SPI_RX_QUAD) { + e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST; + if (spi->mode & SPI_TX_QUAD) + e_rd_cmd |= QUAD_IO_FAST; + } else if (mode_rx & SPI_RX_DUAL) { + e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST; + if (spi->mode & SPI_TX_DUAL) + e_rd_cmd |= DUAL_IO_FAST; + } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) { + e_rd_cmd = ARRAY_SLOW; + } else { + e_rd_cmd = RD_NORM; + } + - ret = spi_flash_scan(flash); + ret = spi_flash_scan(flash, e_rd_cmd);
Quoted 4 lines
I've spent a lot of time working on the QSPI memory topic so I can tell you that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support, please let me know.
I understand your points, thanks for that and anyway this spi-nor work is a starting point for both syncing with Linux as well with new feature or for better tunning. And more over I started this work in 2014 end and it's been reviewing over and over and we finally landed up with MTD driver model.
So, please wait for sometime until this gets merged we definitely work together for better tunning, thanks!
Signature · 1 line
Jagan
cover sf: fix support of QSPI memories and controllers
Hello Jagan,
Quoted 163 lines · Jagan Teki
Quoted 151 lines · Cyrille Pitchen
Le 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 36 lines · Cyrille Pitchen
Quoted 26 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a memory.
Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()Quoted 8 lines
sf: fix selection of supported READ commands for QSPI memories
sf: fix detection of QSPI memories when they boot in Quad or Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controllerQuoted 4 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1] http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-next
Hi Jagan,
I've started to have a look on your branch. I hope it's not to late for few comments:
Globally I see the new code attend to match the spi-nor framework from Linux. OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.
First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit to add support to Micron QSPI memories was reverted since it didn't work alone. In his reply, Brian agreed the code was not tested and should not have been merged.
This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol change at the QSPI memory side. This applies to Micron memories when they enter their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the structspi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the .read_mmap() also.
- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.(Q)SPI controller drivers cannot guess the protocol to be used from the command op code. Indeed, taking the Micron case as un example, the very same
0xebop code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or with the SPI 4-4-4 protocol (Micron Quad I/O mode).Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles (if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)So the
SNOR_OP_READ_1_1_2_IOmacro for the Fast Read Dual I/O command (as opposed to the macroSNOR_OP_READ_1_1_2macro for the Fast Read Dual Output command) doesn't make sense: it should be namedSNOR_OP_READ_1_2_2.Then about the value used for the dummy cycles, it's not always true that we don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to during Fast Read operations to make the memory enter/leaver its Continuous Read mode. Once is Continuous Read mode, the op code byte is no longer sent, it is implicit and the command actually starts from the address cycles. This mode is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by updating the relevant bit in some configuration register (e.g. setting the XIP bit in Micron Volatile Configuration Register) or by choosing the right op code (e.g. for Winbond memories in QPI mode, both the
0x0band0xebop codes can be used for Fast Read 4-4-4 operation but only the0xebop code cares about the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.Besides when sending a regular JEDEC Read ID (
0x9f) command to probe the (Q)SPI memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not already enabled. This not always true, some early bootloarders, such as the sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from the QSPI memory. If so, the QSPI memory no longer replies to the0x9fcommand in SPI 1-1-1 protocol but instead to the0xafcommand in SPI 4-4-4 protocol.Finally, about the proper way to describe the SPI controller capabilities, the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4 protocols. Maybe some SPI controllers support the first protocol but not the latest. It could be good to add another argument tospi_nor_scan()providing an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI memory and select the proper protocol, this new argument should use the same range of values as the .flash_read field in the structspi_nor_infoused to describe the SPI memories.For backward compatibility, the m25p80 driver could then convert the SPI modes into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related to
spi_flash_probe_slave()insf_probe.c:/* Convert SPI mode_rx and mode to SPI flash read commands */(quoted diff) +16
-1+ mode_rx = spi->mode_rx; + if (mode_rx & SPI_RX_QUAD) { + e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST; + if (spi->mode & SPI_TX_QUAD) + e_rd_cmd |= QUAD_IO_FAST; + } else if (mode_rx & SPI_RX_DUAL) { + e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST; + if (spi->mode & SPI_TX_DUAL) + e_rd_cmd |= DUAL_IO_FAST; + } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) { + e_rd_cmd = ARRAY_SLOW; + } else { + e_rd_cmd = RD_NORM; + } + - ret = spi_flash_scan(flash); + ret = spi_flash_scan(flash, e_rd_cmd);Quoted 4 lines
I've spent a lot of time working on the QSPI memory topic so I can tell you that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support, please let me know.I understand your points, thanks for that and anyway this spi-nor work is a starting point for both syncing with Linux as well with new feature or for better tunning. And more over I started this work in 2014 end and it's been reviewing over and over and we finally landed up with MTD driver model.
Quoted 2 lines
So, please wait for sometime until this gets merged we definitely work together for better tunning, thanks!
If I understand Cyrille's post correctly, it is not about better tuning, it is about fixing existing issues, right? I mean, Cyrille is talking about situations where the code will be not simply slow, but plain wrong, correct?
If so, and since it appears Cyrills's patch series are bug fixes which the framework would not properly work if it did not integrate them anyway, I would agree with Marek that it makes more sense applying Cyrille's patches first.
Quoted 2 lines
Signature · 1 line
Jagan
Amicalement,
Signature · 1 line
Albert.
cover sf: fix support of QSPI memories and controllers
Hi Albert,
Quoted 175 lines · Albert ARIBAUD
Hello Jagan,
Quoted 163 lines · Jagan Teki
Quoted 151 lines · Cyrille Pitchen
Le 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 36 lines · Cyrille Pitchen
Quoted 26 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a memory.
Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()Quoted 8 lines
sf: fix selection of supported READ commands for QSPI memories
sf: fix detection of QSPI memories when they boot in Quad or Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controllerQuoted 4 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1] http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-next
Hi Jagan,
I've started to have a look on your branch. I hope it's not to late for few comments:
Globally I see the new code attend to match the spi-nor framework from Linux. OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.
First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit to add support to Micron QSPI memories was reverted since it didn't work alone. In his reply, Brian agreed the code was not tested and should not have been merged.
This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol change at the QSPI memory side. This applies to Micron memories when they enter their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the structspi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the.read_mmap() also.- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.(Q)SPI controller drivers cannot guess the protocol to be used from the command op code. Indeed, taking the Micron case as un example, the very same
0xebop code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or with the SPI 4-4-4 protocol (Micron Quad I/O mode).Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles (if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)So the
SNOR_OP_READ_1_1_2_IOmacro for the Fast Read Dual I/O command (as opposed to the macroSNOR_OP_READ_1_1_2macro for the Fast Read Dual Output command) doesn't make sense: it should be namedSNOR_OP_READ_1_2_2.Then about the value used for the dummy cycles, it's not always true that we don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to during Fast Read operations to make the memory enter/leaver its Continuous Read mode. Once is Continuous Read mode, the op code byte is no longer sent, it is implicit and the command actually starts from the address cycles. This mode is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by updating the relevant bit in some configuration register (e.g. setting the XIP bit in Micron Volatile Configuration Register) or by choosing the right op code (e.g. for Winbond memories in QPI mode, both the
0x0band0xebop codes can be used for Fast Read 4-4-4 operation but only the0xebop code cares about the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.Besides when sending a regular JEDEC Read ID (
0x9f) command to probe the (Q)SPI memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not already enabled. This not always true, some early bootloarders, such as the sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from the QSPI memory. If so, the QSPI memory no longer replies to the0x9fcommand in SPI 1-1-1 protocol but instead to the0xafcommand in SPI 4-4-4 protocol.Finally, about the proper way to describe the SPI controller capabilities, the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4 protocols. Maybe some SPI controllers support the first protocol but not the latest. It could be good to add another argument tospi_nor_scan()providing an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI memory and select the proper protocol, this new argument should use the same range of values as the .flash_read field in the structspi_nor_infoused to describe the SPI memories.For backward compatibility, the m25p80 driver could then convert the SPI modes into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related to
spi_flash_probe_slave()insf_probe.c:/* Convert SPI mode_rx and mode to SPI flash read commands */(quoted diff) +16
-1+ mode_rx = spi->mode_rx; + if (mode_rx & SPI_RX_QUAD) { + e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST; + if (spi->mode & SPI_TX_QUAD) + e_rd_cmd |= QUAD_IO_FAST; + } else if (mode_rx & SPI_RX_DUAL) { + e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST; + if (spi->mode & SPI_TX_DUAL) + e_rd_cmd |= DUAL_IO_FAST; + } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) { + e_rd_cmd = ARRAY_SLOW; + } else { + e_rd_cmd = RD_NORM; + } + - ret = spi_flash_scan(flash); + ret = spi_flash_scan(flash, e_rd_cmd);Quoted 4 lines
I've spent a lot of time working on the QSPI memory topic so I can tell you that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support, please let me know.I understand your points, thanks for that and anyway this spi-nor work is a starting point for both syncing with Linux as well with new feature or for better tunning. And more over I started this work in 2014 end and it's been reviewing over and over and we finally landed up with MTD driver model.
Quoted 2 lines
So, please wait for sometime until this gets merged we definitely work together for better tunning, thanks!
If I understand Cyrille's post correctly, it is not about better tuning, it is about fixing existing issues, right? I mean, Cyrille is talking about situations where the code will be not simply slow, but plain wrong, correct?
Quoted 4 lines
If so, and since it appears Cyrills's patch series are bug fixes which the framework would not properly work if it did not integrate them anyway, I would agree with Marek that it makes more sense applying Cyrille's patches first.
OK, if these are bug fixes then what is the issue on working on top of spi-nor? and more over this series is on ML just now and need a proper review as well and will take some time too. I have planned spi-nor series for this release better work on this series - thanks!
Signature · 1 line
Jagan
cover sf: fix support of QSPI memories and controllers
Hello Jagan,
Quoted 178 lines · Jagan Teki
Hi Albert,
Quoted 175 lines · Albert ARIBAUD
Hello Jagan,
Quoted 163 lines · Jagan Teki
Quoted 151 lines · Cyrille Pitchen
Le 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 36 lines · Cyrille Pitchen
Quoted 26 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a memory.
Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()Quoted 8 lines
sf: fix selection of supported READ commands for QSPI memories
sf: fix detection of QSPI memories when they boot in Quad or Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controllerQuoted 4 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1] http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-next
Hi Jagan,
I've started to have a look on your branch. I hope it's not to late for few comments:
Globally I see the new code attend to match the spi-nor framework from Linux. OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.
First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit to add support to Micron QSPI memories was reverted since it didn't work alone. In his reply, Brian agreed the code was not tested and should not have been merged.
This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol change at the QSPI memory side. This applies to Micron memories when they enter their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the structspi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the.read_mmap() also.- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.(Q)SPI controller drivers cannot guess the protocol to be used from the command op code. Indeed, taking the Micron case as un example, the very same
0xebop code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or with the SPI 4-4-4 protocol (Micron Quad I/O mode).Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles (if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)So the
SNOR_OP_READ_1_1_2_IOmacro for the Fast Read Dual I/O command (as opposed to the macroSNOR_OP_READ_1_1_2macro for the Fast Read Dual Output command) doesn't make sense: it should be namedSNOR_OP_READ_1_2_2.Then about the value used for the dummy cycles, it's not always true that we don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to during Fast Read operations to make the memory enter/leaver its Continuous Read mode. Once is Continuous Read mode, the op code byte is no longer sent, it is implicit and the command actually starts from the address cycles. This mode is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by updating the relevant bit in some configuration register (e.g. setting the XIP bit in Micron Volatile Configuration Register) or by choosing the right op code (e.g. for Winbond memories in QPI mode, both the
0x0band0xebop codes can be used for Fast Read 4-4-4 operation but only the0xebop code cares about the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.Besides when sending a regular JEDEC Read ID (
0x9f) command to probe the (Q)SPI memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not already enabled. This not always true, some early bootloarders, such as the sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from the QSPI memory. If so, the QSPI memory no longer replies to the0x9fcommand in SPI 1-1-1 protocol but instead to the0xafcommand in SPI 4-4-4 protocol.Finally, about the proper way to describe the SPI controller capabilities, the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4 protocols. Maybe some SPI controllers support the first protocol but not the latest. It could be good to add another argument tospi_nor_scan()providing an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI memory and select the proper protocol, this new argument should use the same range of values as the .flash_read field in the structspi_nor_infoused to describe the SPI memories.For backward compatibility, the m25p80 driver could then convert the SPI modes into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related to
spi_flash_probe_slave()insf_probe.c:/* Convert SPI mode_rx and mode to SPI flash read commands */(quoted diff) +16
-1+ mode_rx = spi->mode_rx; + if (mode_rx & SPI_RX_QUAD) { + e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST; + if (spi->mode & SPI_TX_QUAD) + e_rd_cmd |= QUAD_IO_FAST; + } else if (mode_rx & SPI_RX_DUAL) { + e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST; + if (spi->mode & SPI_TX_DUAL) + e_rd_cmd |= DUAL_IO_FAST; + } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) { + e_rd_cmd = ARRAY_SLOW; + } else { + e_rd_cmd = RD_NORM; + } + - ret = spi_flash_scan(flash); + ret = spi_flash_scan(flash, e_rd_cmd);Quoted 4 lines
I've spent a lot of time working on the QSPI memory topic so I can tell you that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support, please let me know.I understand your points, thanks for that and anyway this spi-nor work is a starting point for both syncing with Linux as well with new feature or for better tunning. And more over I started this work in 2014 end and it's been reviewing over and over and we finally landed up with MTD driver model.
Quoted 2 lines
So, please wait for sometime until this gets merged we definitely work together for better tunning, thanks!
If I understand Cyrille's post correctly, it is not about better tuning, it is about fixing existing issues, right? I mean, Cyrille is talking about situations where the code will be not simply slow, but plain wrong, correct?
Quoted 7 lines
Quoted 4 lines
If so, and since it appears Cyrills's patch series are bug fixes which the framework would not properly work if it did not integrate them anyway, I would agree with Marek that it makes more sense applying Cyrille's patches first.
OK, if these are bug fixes then what is the issue on working on top of spi-nor?
I believe you said spi-nor is not going to be submitted again until a couple of weeks, and then there will be a review period; that may not fit 2016.05. Cyrille's fixes could go out of the review phase before spi-nor does, and possibly even be ready for 2016.05.
Quoted 2 lines
and more over this series is on ML just now and need a proper review as well and will take some time too.
Yes, but non-structural bugfixes are easier and quicker to test than structural changes (which btw won't be entirely testable until the bug fixes are applied IIUC).
Quoted 2 lines
I have planned spi-nor
series for this release better work on this series - thanks!
But if spi-nor is released in 2016.05 without Cyrille's patches, there will be known bugs unfixed, right?
Quoted 2 lines
Signature · 1 line
Jagan
Amicalement,
Signature · 1 line
Albert.
cover sf: fix support of QSPI memories and controllers
In reply to Jagan TekiLe 16/03/2016 15:14, Jagan Teki a ?crit :
Quoted 152 lines · Cyrille Pitchen
Quoted 151 lines
Le 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 36 lines · Cyrille Pitchen
Quoted 26 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a memory.
Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()Quoted 8 lines
sf: fix selection of supported READ commands for QSPI memories
sf: fix detection of QSPI memories when they boot in Quad or Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controllerQuoted 4 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1] http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-next
Hi Jagan,
I've started to have a look on your branch. I hope it's not to late for few comments:
Globally I see the new code attend to match the spi-nor framework from Linux. OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.
First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit to add support to Micron QSPI memories was reverted since it didn't work alone. In his reply, Brian agreed the code was not tested and should not have been merged.
This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol change at the QSPI memory side. This applies to Micron memories when they enter their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the structspi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the .read_mmap() also.
- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.(Q)SPI controller drivers cannot guess the protocol to be used from the command op code. Indeed, taking the Micron case as un example, the very same
0xebop code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or with the SPI 4-4-4 protocol (Micron Quad I/O mode).Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles (if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)So the
SNOR_OP_READ_1_1_2_IOmacro for the Fast Read Dual I/O command (as opposed to the macroSNOR_OP_READ_1_1_2macro for the Fast Read Dual Output command) doesn't make sense: it should be namedSNOR_OP_READ_1_2_2.Then about the value used for the dummy cycles, it's not always true that we don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to during Fast Read operations to make the memory enter/leaver its Continuous Read mode. Once is Continuous Read mode, the op code byte is no longer sent, it is implicit and the command actually starts from the address cycles. This mode is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by updating the relevant bit in some configuration register (e.g. setting the XIP bit in Micron Volatile Configuration Register) or by choosing the right op code (e.g. for Winbond memories in QPI mode, both the
0x0band0xebop codes can be used for Fast Read 4-4-4 operation but only the0xebop code cares about the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.Besides when sending a regular JEDEC Read ID (
0x9f) command to probe the (Q)SPI memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not already enabled. This not always true, some early bootloarders, such as the sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from the QSPI memory. If so, the QSPI memory no longer replies to the0x9fcommand in SPI 1-1-1 protocol but instead to the0xafcommand in SPI 4-4-4 protocol.Finally, about the proper way to describe the SPI controller capabilities, the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4 protocols. Maybe some SPI controllers support the first protocol but not the latest. It could be good to add another argument tospi_nor_scan()providing an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI memory and select the proper protocol, this new argument should use the same range of values as the .flash_read field in the structspi_nor_infoused to describe the SPI memories.For backward compatibility, the m25p80 driver could then convert the SPI modes into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related to
spi_flash_probe_slave()insf_probe.c:/* Convert SPI mode_rx and mode to SPI flash read commands */(quoted diff) +16
-1+ mode_rx = spi->mode_rx; + if (mode_rx & SPI_RX_QUAD) { + e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST; + if (spi->mode & SPI_TX_QUAD) + e_rd_cmd |= QUAD_IO_FAST; + } else if (mode_rx & SPI_RX_DUAL) { + e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST; + if (spi->mode & SPI_TX_DUAL) + e_rd_cmd |= DUAL_IO_FAST; + } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) { + e_rd_cmd = ARRAY_SLOW; + } else { + e_rd_cmd = RD_NORM; + } + - ret = spi_flash_scan(flash); + ret = spi_flash_scan(flash, e_rd_cmd);
Quoted 9 lines
Quoted 4 lines
I've spent a lot of time working on the QSPI memory topic so I can tell you that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support, please let me know.I understand your points, thanks for that and anyway this spi-nor work is a starting point for both syncing with Linux as well with new feature or for better tunning. And more over I started this work in 2014 end and it's been reviewing over and over and we finally landed up with MTD driver model.
So, please wait for sometime until this gets merged we definitely work together for better tunning, thanks!
OK, no problem!
I will just send the additional patches I used to test with the sama5d2 xplained board.
They are not related with the spi_flash/spi-nor framework itself but they are part of a WIP update of the sama5d2_xplained board support. If some people need those patches to unblock their own developments using QSPI memories on sama5d2 SoCs, all the material will be available :)
Best regards,
Cyrille
PATCH 1/4 rework board config files
--- board/atmel/sama5d2_xplained/Kconfig | 14 ++++++++++++++ board/atmel/sama5d2_xplained/sama5d2_xplained.c | 14 +++++++++----- drivers/mmc/Kconfig | 6 ++++++ include/configs/at91-sama5_common.h | 10 ++++++++++ include/configs/sama5d2_xplained.h | 15 ++------------- 5 files changed, 41 insertions(+), 18 deletions(-)
board/atmel/sama5d2_xplained/Kconfig +14 -0
@@ -12,4 +12,18 @@ config SYS_SOC config SYS_CONFIG_NAME default "sama5d2_xplained" +config ATMEL_SPI0 + bool "SPI0" + default y + +config ATMEL_SDHCI0 + bool "SDHCI0" + select ATMEL_SDHCI + default y + +config ATMEL_SDHCI1 + bool "SDHCI1" + select ATMEL_SDHCI + default y + endif
board/atmel/sama5d2_xplained/sama5d2_xplained.c +9 -5
@@ -25,6 +25,7 @@DECLARE_GLOBAL_DATA_PTR ; +#ifndef CONFIG_DM_SPI int spi_cs_is_valid (unsigned int bus,unsigned int cs) {return bus ==0 && cs ==0 ;
@@ -39,7 +40,9 @@ void spi_cs_deactivate(struct spi_slave *slave) {atmel_pio4_set_pio_output (AT91_PIO_PORTA ,17 ,1 ); } +#endif +#ifdef CONFIG_ATMEL_SPI0 static void board_spi0_hw_init (void ) {atmel_pio4_set_a_periph (AT91_PIO_PORTA ,14 ,0 );
@@ -50,6 +53,7 @@ static void board_spi0_hw_init(void) at91_periph_clk_enable(ATMEL_ID_SPI0); } +#endif static void board_usb_hw_init (void ) {
@@ -157,6 +161,7 @@ static void board_gmac_hw_init(void)at91_periph_clk_enable (ATMEL_ID_GMAC ); } +#ifdef CONFIG_ATMEL_SDHCI0 static void board_sdhci0_hw_init (void ) {atmel_pio4_set_a_periph (AT91_PIO_PORTA ,0 ,0 );/* SDMMC0_CK */
@@ -176,7 +181,9 @@ static void board_sdhci0_hw_init(void)at91_enable_periph_generated_clk (ATMEL_ID_SDMMC0 ,GCK_CSS_PLLA_CLK ,1 ); } +#endif +#ifdef CONFIG_ATMEL_SDHCI1 static void board_sdhci1_hw_init (void ) {atmel_pio4_set_e_periph (AT91_PIO_PORTA ,18 ,0 );/* SDMMC1_DAT0 */
@@ -192,6 +199,7 @@ static void board_sdhci1_hw_init(void)at91_enable_periph_generated_clk (ATMEL_ID_SDMMC1 , GCK_CSS_PLLA_CLK, 1); } +#endif int board_mmc_init (bd_t *bis) {
@@ -230,17 +238,15 @@ int board_init(void)/* address of boot parameters */ gd->bd->bi_boot_params =CONFIG_SYS_SDRAM_BASE +0x100 ; -#ifdef CONFIG_ATMEL_SPI +#ifdef CONFIG_ATMEL_SPI0 board_spi0_hw_init ();#endif -#ifdef CONFIG_ATMEL_SDHCI #ifdef CONFIG_ATMEL_SDHCI0 board_sdhci0_hw_init ();#endif #ifdef CONFIG_ATMEL_SDHCI1 board_sdhci1_hw_init ();#endif -#endif #ifdef CONFIG_MACB board_gmac_hw_init ();#endif
@@ -289,14 +295,12 @@ void spl_board_init(void)#ifdef CONFIG_SYS_USE_SERIALFLASH board_spi0_hw_init ();#endif -#ifdef CONFIG_ATMEL_SDHCI #ifdef CONFIG_ATMEL_SDHCI0 board_sdhci0_hw_init ();#endif #ifdef CONFIG_ATMEL_SDHCI1 board_sdhci1_hw_init ();#endif -#endif }static void ddrc_conf (struct atmel_mpddrc_config *ddrc)
drivers/mmc/Kconfig +6 -0
@@ -49,4 +49,10 @@ config MMC_UNIPHIER help This selects support for the SD/MMC Host Controller on UniPhier SoCs. +config ATMEL_SDHCI + bool "Atmel SD Host Controller Interface" + depends on ARCH_AT91 + help + This enables support for the Atmel SD/eMMC controller + endmenu
include/configs/at91-sama5_common.h +10 -0
@@ -104,6 +104,16 @@"sf read 0x21000000 0x60000 0xc000; " \"sf read 0x22000000 0x6c000 0x394000; " \ "bootz 0x22000000 - 0x21000000" +#elif CONFIG_SYS_USE_QSPIFLASH +/* u-boot env in QSPI flash, by default is bus 0 and cs 0 */ +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_OFFSET 0x10000 +#define CONFIG_ENV_SIZE 0x10000 +#define CONFIG_ENV_SECT_SIZE 0x10000 +#define CONFIG_BOOTCOMMAND "sf probe 0; " \ + "sf read 0x21000000 0x60000 0x10000; " \ + "sf read 0x22000000 0x70000 0x500000; " \ + "bootz 0x22000000 - 0x21000000"#endif #endif
include/configs/sama5d2_xplained.h +2 -13
@@ -16,6 +16,8 @@#include "at91-sama5_common.h" /* serial console */ +#undef CONFIG_BAUDRATE +#define CONFIG_BAUDRATE 57600#define CONFIG_ATMEL_USART #define CONFIG_USART_BASE ATMEL_BASE_UART1#define CONFIG_USART_ID ATMEL_ID_UART1
@@ -37,16 +39,6 @@#undef CONFIG_AT91_GPIO#define CONFIG_ATMEL_PIO4 -/* SerialFlash */ -#ifdef CONFIG_CMD_SF -#define CONFIG_ATMEL_SPI -#define CONFIG_ATMEL_SPI0 -#define CONFIG_SPI_FLASH_ATMEL -#define CONFIG_SF_DEFAULT_BUS 0 -#define CONFIG_SF_DEFAULT_CS 0 -#define CONFIG_SF_DEFAULT_SPEED 30000000 -#endif -/* NAND flash */ #undef CONFIG_CMD_NAND
@@ -57,9 +49,6 @@#define CONFIG_MMC #define CONFIG_GENERIC_MMC #define CONFIG_SDHCI -#define CONFIG_ATMEL_SDHCI -#define CONFIG_ATMEL_SDHCI0 -#define CONFIG_ATMEL_SDHCI1 #define CONFIG_SUPPORT_EMMC_BOOT #endif
Signature · 1 line
1.8.2.2
PATCH 2/4 sama5d2_xplained: add support of QSPI controllers
--- board/atmel/sama5d2_xplained/Kconfig | 6 ++++++ board/atmel/sama5d2_xplained/sama5d2_xplained.c | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+)
board/atmel/sama5d2_xplained/Kconfig +6 -0
@@ -26,4 +26,10 @@ config ATMEL_SDHCI1 select ATMEL_SDHCI default y +config ATMEL_QSPI0 + bool "QSPI0" + select DM_SPI + select ATMEL_QSPI + default n + endif
board/atmel/sama5d2_xplained/sama5d2_xplained.c +18 -0
@@ -55,6 +55,21 @@ static void board_spi0_hw_init(void) }#endif +#ifdef CONFIG_ATMEL_QSPI0 +static void board_qspi0_hw_init (void ) +{ +/* QSPI0 - ioset 3 */ +atmel_pio4_set_f_periph (AT91_PIO_PORTA ,22 ,0 );/* SCK */ +atmel_pio4_set_f_periph (AT91_PIO_PORTA ,23 ,0 );/* CS */ +atmel_pio4_set_f_periph (AT91_PIO_PORTA ,24 ,1 );/* IO0 */ +atmel_pio4_set_f_periph (AT91_PIO_PORTA ,25 ,1 );/* IO1 */ +atmel_pio4_set_f_periph (AT91_PIO_PORTA ,26 ,1 );/* IO2 */ +atmel_pio4_set_f_periph (AT91_PIO_PORTA ,27 ,1 );/* IO3 */ + +at91_periph_clk_enable (ATMEL_ID_QSPI0 ); +} +#endif +static void board_usb_hw_init (void ) {atmel_pio4_set_pio_output (AT91_PIO_PORTB ,10 ,1 );
@@ -241,6 +256,9 @@ int board_init(void)#ifdef CONFIG_ATMEL_SPI0 board_spi0_hw_init ();#endif +#ifdef CONFIG_ATMEL_QSPI0 +board_qspi0_hw_init (); +#endif #ifdef CONFIG_ATMEL_SDHCI0 board_sdhci0_hw_init ();#endif
Signature · 1 line
1.8.2.2
PATCH 3/4 dts: add dts file for Atmel sama5d2 xplained board
In reply to Cyrille Pitchen--- arch/arm/dts/Makefile | 3 +++ arch/arm/dts/at91-sama5d2_xplained.dts | 33 +++++++++++++++++++++++++++++++++ arch/arm/dts/sama5d2.dtsi | 19 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 arch/arm/dts/at91-sama5d2_xplained.dts create mode 100644 arch/arm/dts/sama5d2.dtsi
arch/arm/dts/Makefile +3 -0
@@ -207,6 +207,9 @@ dtb-$(CONFIG_SOC_KEYSTONE) += k2hk-evm.dtb \ k2e-evm.dtb \ k2g-evm.dtb +dtb-$(CONFIG_ARCH_AT91) += \ + at91-sama5d2_xplained.dtb + targets += $(dtb-y) # Add any required device tree compiler flags here
arch/arm/dts/at91-sama5d2_xplained.dts new file +33 -0
@@ -0,0 +1,33 @@ +/dts-v1/; +#include "sama5d2.dtsi" + +/ { + model = "Atmel SAMA5D2 Xplained"; + compatible = "atmel,sama5d2-xplained", "atmel,sama5d2", "atmel,sama5"; + + chosen { + stdout-path = "serial0"; + }; +}; + +&qspi0 { + status = "okay"; + + flash at 0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "atmel,sama5d2-qspi-flash"; + reg = <0>; + spi-max-frequency = <83000000>; + + partition at 00000000 { + label = "boot"; + reg = <0x00000000 0x00c00000>; + }; + + partition at 00c00000 { + label = "rootfs"; + reg = <0x00c00000 0x00000000>; + }; + }; +};
arch/arm/dts/sama5d2.dtsi new file +19 -0
@@ -0,0 +1,19 @@ +#include "skeleton.dtsi" + +/ { + model = "Atmel SAMA5D2 family SoC"; + compatible = "atmel,sama5d2"; + + aliases { + spi0 = &qspi0; + }; + + qspi0: spi at f0020000 { + compatible = "atmel,sama5d2-qspi"; + reg = <0xf0020000 0x100>, <0xd0000000 0x08000000>; + reg-names = "qspi_base", "qspi_mmap"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; +};
Signature · 1 line
1.8.2.2
PATCH 4/4 sf: fix sf probe
In reply to Cyrille PitchenThis patch fixes the "sf probe" command. The very first SPI flash probe passes, for instance when u-boot tries to read its environment settings from a (Q)SPI memory but next "sf probe" commands fail because the flash memory node is unbound from the SPI controller children nodes.
--- cmd/sf.c | 1 - 1 file changed, 1 deletion(-)
cmd/sf.c +0 -1
@@ -123,7 +123,6 @@ static int do_spi_flash_probe(int argc, char * const argv[]) ret =spi_find_bus_and_cs (bus, cs, &bus_dev, &new);if (!ret) {device_remove (new); -device_unbind (new); } flash =NULL ; ret =spi_flash_probe_bus_cs (bus, cs, speed, mode, &new);
Signature · 1 line
1.8.2.2
cover sf: fix support of QSPI memories and controllers
In reply to Jagan TekiHi All,
please excuse the late reply to this thread. But I'm very interested in QSPI, as one of my customers uses Micron QSPI NOR and really wants to take full advantage of the device (quad access) to speed up the overall boot process. This is on SoCFPGA btw.
Please allow me a few comments below.
Quoted 197 lines · Jagan Teki
Quoted 196 lines · Cyrille Pitchen
Le 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 38 lines · Cyrille Pitchen
Quoted 28 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a
memory.Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()
sf: fix selection of supported READ commands for QSPI memoriesQuoted 8 lines
sf: fix detection of QSPI memories when they boot in Quad or
Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controllerQuoted 8 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1]
http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-nextHi Jagan,
I've started to have a look on your branch. I hope it's not to late for few
comments:Globally I see the new code attend to match the spi-nor framework from Linux.
OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit
to add support to Micron QSPI memories was reverted since it didn't work alone.
In his reply, Brian agreed the code was not tested and should not have been
merged.This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol
change at the QSPI memory side. This applies to Micron memories when they enter
their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y
protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI
mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the structspi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the
.read_mmap() also.
- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.(Q)SPI controller drivers cannot guess the protocol to be used from the command
op code. Indeed, taking the Micron case as un example, the very same0xebop
code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or
with the SPI 4-4-4 protocol (Micron Quad I/O mode).Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles
(if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)So the
SNOR_OP_READ_1_1_2_IOmacro for the Fast Read Dual I/O command (as opposed to the macroSNOR_OP_READ_1_1_2macro for the Fast Read Dual Output
command) doesn't make sense: it should be namedSNOR_OP_READ_1_2_2.Then about the value used for the dummy cycles, it's not always true that we
don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to
during Fast Read operations to make the memory enter/leaver its Continuous Read
mode. Once is Continuous Read mode, the op code byte is no longer sent, it is
implicit and the command actually starts from the address cycles. This mode
is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by
updating the relevant bit in some configuration register (e.g. setting the XIP
bit in Micron Volatile Configuration Register) or by choosing the right op code
(e.g. for Winbond memories in QPI mode, both the0x0band0xebop codes can
be used for Fast Read 4-4-4 operation but only the0xebop code cares about
the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.Besides when sending a regular JEDEC Read ID (
0x9f) command to probe the (Q)SPI
memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not
already enabled. This not always true, some early bootloarders, such as the
sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from
the QSPI memory. If so, the QSPI memory no longer replies to the0x9fcommand
in SPI 1-1-1 protocol but instead to the0xafcommand in SPI 4-4-4 protocol.Finally, about the proper way to describe the SPI controller capabilities,
the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4
protocols. Maybe some SPI controllers support the first protocol but not the
latest. It could be good to add another argument tospi_nor_scan()providing
an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI
memory and select the proper protocol, this new argument should use the same
range of values as the .flash_read field in the structspi_nor_infoused to
describe the SPI memories.For backward compatibility, the m25p80 driver could then convert the SPI modes
into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related tospi_flash_probe_slave()insf_probe.c:/* Convert SPI mode_rx and mode to SPI flash read commands */(quoted diff) +16
-1+ mode_rx = spi->mode_rx; + if (mode_rx & SPI_RX_QUAD) { + e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST; + if (spi->mode & SPI_TX_QUAD) + e_rd_cmd |= QUAD_IO_FAST; + } else if (mode_rx & SPI_RX_DUAL) { + e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST; + if (spi->mode & SPI_TX_DUAL) + e_rd_cmd |= DUAL_IO_FAST; + } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) { + e_rd_cmd = ARRAY_SLOW; + } else { + e_rd_cmd = RD_NORM; + } + - ret = spi_flash_scan(flash); + ret = spi_flash_scan(flash, e_rd_cmd);
Quoted 6 lines
Quoted 6 lines
I've spent a lot of time working on the QSPI memory topic so I can tell you
that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support,
please let me know.
Thanks Cyrille, for this very detailed and good explanation. This is really appreciated. And I really hope that Jagan will get back to your generous offer, to assist with any such QSPI NOR related problems. I'll definitely remember this and might bug you at some time... ;)
Quoted 8 lines
I understand your points, thanks for that and anyway this spi-nor work is a starting point for both syncing with Linux as well with new feature or for better tunning. And more over I started this work in 2014 end and it's been reviewing over and over and we finally landed up with MTD driver model.
So, please wait for sometime until this gets merged we definitely work together for better tunning, thanks!
Jagan, what is the current plan here? I have to admit that I didn't check closely on your SPI-NOR work lately, sorry. So I can't really comment with a profound deep knowledge. But from what I read in Cyrille's patchset and explanation above, his patchset fixes some issues and brings us also more in line with the (upcoming) Linux framework. So I would really love to see this integrated into mainline quickly. Allowing a broader test basis on multiple platforms. Will it be a big task for Cyrille to rebase his patchset on top of your patches? Can you perhaps assist Cyrille with this? Or would it perhaps make sense to postpone your patchset and integrate Cyrille's first instead?
Cyrille, if Jagans rework goes in first, do you already have a plan on when to rebase your patchset on top of this? Or do you see some "show-stoppers" here?
Comments welcome.
Thanks,
Stefan
cover sf: fix support of QSPI memories and controllers
Hi Stefan,
Le 18/03/2016 14:48, Stefan Roese a ?crit :
Quoted 240 lines
Hi All,
please excuse the late reply to this thread. But I'm very interested in QSPI, as one of my customers uses Micron QSPI NOR and really wants to take full advantage of the device (quad access) to speed up the overall boot process. This is on SoCFPGA btw.
Please allow me a few comments below.
Quoted 197 lines · Jagan Teki
Quoted 196 lines · Cyrille Pitchen
Le 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 38 lines · Cyrille Pitchen
Quoted 28 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a
memory.Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()
sf: fix selection of supported READ commands for QSPI memoriesQuoted 8 lines
sf: fix detection of QSPI memories when they boot in Quad or
Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controllerQuoted 8 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1]
http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-nextHi Jagan,
I've started to have a look on your branch. I hope it's not to late for few
comments:Globally I see the new code attend to match the spi-nor framework from Linux.
OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit
to add support to Micron QSPI memories was reverted since it didn't work alone.
In his reply, Brian agreed the code was not tested and should not have been
merged.This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol
change at the QSPI memory side. This applies to Micron memories when they enter
their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y
protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI
mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the structspi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the
.read_mmap() also.
- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.(Q)SPI controller drivers cannot guess the protocol to be used from the command
op code. Indeed, taking the Micron case as un example, the very same0xebop
code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or
with the SPI 4-4-4 protocol (Micron Quad I/O mode).Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles
(if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)So the
SNOR_OP_READ_1_1_2_IOmacro for the Fast Read Dual I/O command (as opposed to the macroSNOR_OP_READ_1_1_2macro for the Fast Read Dual Output
command) doesn't make sense: it should be namedSNOR_OP_READ_1_2_2.Then about the value used for the dummy cycles, it's not always true that we
don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to
during Fast Read operations to make the memory enter/leaver its Continuous Read
mode. Once is Continuous Read mode, the op code byte is no longer sent, it is
implicit and the command actually starts from the address cycles. This mode
is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by
updating the relevant bit in some configuration register (e.g. setting the XIP
bit in Micron Volatile Configuration Register) or by choosing the right op code
(e.g. for Winbond memories in QPI mode, both the0x0band0xebop codes can
be used for Fast Read 4-4-4 operation but only the0xebop code cares about
the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.Besides when sending a regular JEDEC Read ID (
0x9f) command to probe the (Q)SPI
memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not
already enabled. This not always true, some early bootloarders, such as the
sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from
the QSPI memory. If so, the QSPI memory no longer replies to the0x9fcommand
in SPI 1-1-1 protocol but instead to the0xafcommand in SPI 4-4-4 protocol.Finally, about the proper way to describe the SPI controller capabilities,
the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4
protocols. Maybe some SPI controllers support the first protocol but not the
latest. It could be good to add another argument tospi_nor_scan()providing
an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI
memory and select the proper protocol, this new argument should use the same
range of values as the .flash_read field in the structspi_nor_infoused to
describe the SPI memories.For backward compatibility, the m25p80 driver could then convert the SPI modes
into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related tospi_flash_probe_slave()insf_probe.c:/* Convert SPI mode_rx and mode to SPI flash read commands */(quoted diff) +16
-1+ mode_rx = spi->mode_rx; + if (mode_rx & SPI_RX_QUAD) { + e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST; + if (spi->mode & SPI_TX_QUAD) + e_rd_cmd |= QUAD_IO_FAST; + } else if (mode_rx & SPI_RX_DUAL) { + e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST; + if (spi->mode & SPI_TX_DUAL) + e_rd_cmd |= DUAL_IO_FAST; + } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) { + e_rd_cmd = ARRAY_SLOW; + } else { + e_rd_cmd = RD_NORM; + } + - ret = spi_flash_scan(flash); + ret = spi_flash_scan(flash, e_rd_cmd);Quoted 6 lines
Quoted 6 lines
I've spent a lot of time working on the QSPI memory topic so I can tell you
that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support,
please let me know.Thanks Cyrille, for this very detailed and good explanation. This is really appreciated. And I really hope that Jagan will get back to your generous offer, to assist with any such QSPI NOR related problems. I'll definitely remember this and might bug you at some time... ;)
Quoted 8 lines
I understand your points, thanks for that and anyway this spi-nor work is a starting point for both syncing with Linux as well with new feature or for better tunning. And more over I started this work in 2014 end and it's been reviewing over and over and we finally landed up with MTD driver model.
So, please wait for sometime until this gets merged we definitely work together for better tunning, thanks!
Jagan, what is the current plan here? I have to admit that I didn't check closely on your SPI-NOR work lately, sorry. So I can't really comment with a profound deep knowledge. But from what I read in Cyrille's patchset and explanation above, his patchset fixes some issues and brings us also more in line with the (upcoming) Linux framework. So I would really love to see this integrated into mainline quickly. Allowing a broader test basis on multiple platforms. Will it be a big task for Cyrille to rebase his patchset on top of your patches? Can you perhaps assist Cyrille with this? Or would it perhaps make sense to postpone your patchset and integrate Cyrille's first instead?
Quoted 4 lines
Cyrille, if Jagans rework goes in first, do you already have a plan on when to rebase your patchset on top of this? Or do you see some "show-stoppers" here?
Well if I need to rebase my patchset, for sure I will wait for Jagan's rework to be completed and accepted first. I don't think it would be efficient to rebase the QSPI series on the fly before the rework is totally stabilized.
One of the commit message from u-boot-spi.git can sum up the global rework:
"sf: Drop entire spi-flash framework" [1]
Indeed all files from drivers/mtd/spi are deleted, the next commits replace them by new files in the spi-nor folder. These new files are almost some "copy/paste" of drivers/mtd/spi-nor files from Linux.
OK, why not but it also implies that I can't simply rebase my patchset. Since the all files are different it means I have to write a new series of patches from scratch. As I said, I won't start such a work before the new framework is totally accepted and integrated in next releases of u-boot.
I don't say using the Linux code as a reference is a bad idea, indeed there are good things in the spi-nor framework to be taken. For instance, in my own series I added .read_reg() and .write_reg() hooks the same way as done in the Linux source.
I just warn developers that currently the Linux code misses some stuff to support QSPI memories efficiently. As an example, spi_nor_scan() fails to read the JEDEC ID if the QSPI memory is already in QPI mode (Micron, Macronix, Winbond, ...).
This issue didn't exist with regular SPI NOR flash memories as they are almost "stateless" as compared to QSPI memories. SPI memories always use a single protocol, SPI 1-1-1 with MISO and MOSI I/O lines, for all commands. On the other hand, QSPI memories are much complex: you have to deal with many different protocols and find a way to guess the current internal state of the QSPI memory before sending commands to it.
So, this is why I've send all the material I have in the case other developers are blocked and need support for QSPI memories in u-boot.
Best regards,
Cyrille
[1] http://git.denx.de/?p=u-boot/u-boot-spi.git;a=commit;h=7ae4605cd2b3484be9e61874c8323226b42bb9ba
Quoted 6 lines
Comments welcome.
Thanks,
Stefan
cover sf: fix support of QSPI memories and controllers
Hi Cyrille,
Quoted 253 lines · Cyrille Pitchen
Hi Stefan,
Le 18/03/2016 14:48, Stefan Roese a ?crit :
Quoted 240 lines
Hi All,
please excuse the late reply to this thread. But I'm very interested in QSPI, as one of my customers uses Micron QSPI NOR and really wants to take full advantage of the device (quad access) to speed up the overall boot process. This is on SoCFPGA btw.
Please allow me a few comments below.
Quoted 197 lines · Jagan Teki
Quoted 196 lines · Cyrille Pitchen
Le 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 38 lines · Cyrille Pitchen
Quoted 28 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a
memory.Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()
sf: fix selection of supported READ commands for QSPI memoriesQuoted 8 lines
sf: fix detection of QSPI memories when they boot in Quad or
Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controllerQuoted 8 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1]
http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-nextHi Jagan,
I've started to have a look on your branch. I hope it's not to late for few
comments:Globally I see the new code attend to match the spi-nor framework from Linux.
OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit
to add support to Micron QSPI memories was reverted since it didn't work alone.
In his reply, Brian agreed the code was not tested and should not have been
merged.This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol
change at the QSPI memory side. This applies to Micron memories when they enter
their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y
protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI
mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the structspi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the
.read_mmap() also.
- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.(Q)SPI controller drivers cannot guess the protocol to be used from the command
op code. Indeed, taking the Micron case as un example, the very same0xebop
code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or
with the SPI 4-4-4 protocol (Micron Quad I/O mode).Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles
(if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)So the
SNOR_OP_READ_1_1_2_IOmacro for the Fast Read Dual I/O command (as opposed to the macroSNOR_OP_READ_1_1_2macro for the Fast Read Dual Output
command) doesn't make sense: it should be namedSNOR_OP_READ_1_2_2.Then about the value used for the dummy cycles, it's not always true that we
don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to
during Fast Read operations to make the memory enter/leaver its Continuous Read
mode. Once is Continuous Read mode, the op code byte is no longer sent, it is
implicit and the command actually starts from the address cycles. This mode
is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by
updating the relevant bit in some configuration register (e.g. setting the XIP
bit in Micron Volatile Configuration Register) or by choosing the right op code
(e.g. for Winbond memories in QPI mode, both the0x0band0xebop codes can
be used for Fast Read 4-4-4 operation but only the0xebop code cares about
the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.Besides when sending a regular JEDEC Read ID (
0x9f) command to probe the (Q)SPI
memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not
already enabled. This not always true, some early bootloarders, such as the
sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from
the QSPI memory. If so, the QSPI memory no longer replies to the0x9fcommand
in SPI 1-1-1 protocol but instead to the0xafcommand in SPI 4-4-4 protocol.Finally, about the proper way to describe the SPI controller capabilities,
the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4
protocols. Maybe some SPI controllers support the first protocol but not the
latest. It could be good to add another argument tospi_nor_scan()providing
an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI
memory and select the proper protocol, this new argument should use the same
range of values as the .flash_read field in the structspi_nor_infoused to
describe the SPI memories.For backward compatibility, the m25p80 driver could then convert the SPI modes
into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related tospi_flash_probe_slave()insf_probe.c:/* Convert SPI mode_rx and mode to SPI flash read commands */(quoted diff) +16
-1+ mode_rx = spi->mode_rx; + if (mode_rx & SPI_RX_QUAD) { + e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST; + if (spi->mode & SPI_TX_QUAD) + e_rd_cmd |= QUAD_IO_FAST; + } else if (mode_rx & SPI_RX_DUAL) { + e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST; + if (spi->mode & SPI_TX_DUAL) + e_rd_cmd |= DUAL_IO_FAST; + } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) { + e_rd_cmd = ARRAY_SLOW; + } else { + e_rd_cmd = RD_NORM; + } + - ret = spi_flash_scan(flash); + ret = spi_flash_scan(flash, e_rd_cmd);Quoted 6 lines
Quoted 6 lines
I've spent a lot of time working on the QSPI memory topic so I can tell you
that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support,
please let me know.Thanks Cyrille, for this very detailed and good explanation. This is really appreciated. And I really hope that Jagan will get back to your generous offer, to assist with any such QSPI NOR related problems. I'll definitely remember this and might bug you at some time... ;)
Quoted 8 lines
I understand your points, thanks for that and anyway this spi-nor work is a starting point for both syncing with Linux as well with new feature or for better tunning. And more over I started this work in 2014 end and it's been reviewing over and over and we finally landed up with MTD driver model.
So, please wait for sometime until this gets merged we definitely work together for better tunning, thanks!
Jagan, what is the current plan here? I have to admit that I didn't check closely on your SPI-NOR work lately, sorry. So I can't really comment with a profound deep knowledge. But from what I read in Cyrille's patchset and explanation above, his patchset fixes some issues and brings us also more in line with the (upcoming) Linux framework. So I would really love to see this integrated into mainline quickly. Allowing a broader test basis on multiple platforms. Will it be a big task for Cyrille to rebase his patchset on top of your patches? Can you perhaps assist Cyrille with this? Or would it perhaps make sense to postpone your patchset and integrate Cyrille's first instead?
Quoted 4 lines
Cyrille, if Jagans rework goes in first, do you already have a plan on when to rebase your patchset on top of this? Or do you see some "show-stoppers" here?
Well if I need to rebase my patchset, for sure I will wait for Jagan's rework to be completed and accepted first. I don't think it would be efficient to rebase the QSPI series on the fly before the rework is totally stabilized.
Quoted 6 lines
One of the commit message from u-boot-spi.git can sum up the global rework:
"sf: Drop entire spi-flash framework" [1]Indeed all files from
drivers/mtd/spiare deleted, the next commits replace them by new files in the spi-nor folder. These new files are almost some "copy/paste" ofdrivers/mtd/spi-norfiles from Linux.
Yeah.. the idea of using Linux spi-nor is like u-boot also facing similar issue where Linux facing like spi drivers became more flash centric, and it's not totally same design as Linux. We took the idea from Linux and have MTD driver model on top of it. The whole idea to add this is to follow the u-boot driver model principle and if the stack look some how similar to Linux then the development is as faster as, when
compared to maintain separate thread of development - this is very legacy story I have been saying on this on ML for year back.
And did you find any issues with this spi-nor series?
Quoted 6 lines
OK, why not but it also implies that I can't simply rebase my patchset. Since the all files are different it means I have to write a new series of patches from scratch. As I said, I won't start such a work before the new framework is totally accepted and integrated in next releases of u-boot.
Quoted 14 lines
I don't say using the Linux code as a reference is a bad idea, indeed there are good things in the spi-nor framework to be taken. For instance, in my own series I added .read_reg() and .write_reg() hooks the same way as done in the Linux source.
I just warn developers that currently the Linux code misses some stuff to support QSPI memories efficiently. As an example,spi_nor_scan()fails to read the JEDEC ID if the QSPI memory is already in QPI mode (Micron, Macronix, Winbond, ...).
This issue didn't exist with regular SPI NOR flash memories as they are almost "stateless" as compared to QSPI memories. SPI memories always use a single protocol, SPI 1-1-1 with MISO and MOSI I/O lines, for all commands. On the other hand, QSPI memories are much complex: you have to deal with many different protocols and find a way to guess the current internal state of the QSPI memory before sending commands to it.
OK, I understand that you sent separate patches, are these patches fix this issue?
https://patchwork.ozlabs.org/patch/598527/
https://patchwork.ozlabs.org/patch/598528/
https://patchwork.ozlabs.org/patch/598530/
https://patchwork.ozlabs.org/patch/598532/
If so, then I will start reviewing these and will push these changes first and will rebase spi-nor on top of this.
thanks!
Signature · 1 line
Jagan.
cover sf: fix support of QSPI memories and controllers
Hi Jagan,
Le 21/03/2016 10:07, Jagan Teki a ?crit :
Quoted 273 lines
Hi Cyrille,
Quoted 253 lines · Cyrille Pitchen
Hi Stefan,
Le 18/03/2016 14:48, Stefan Roese a ?crit :
Quoted 240 lines
Hi All,
please excuse the late reply to this thread. But I'm very interested in QSPI, as one of my customers uses Micron QSPI NOR and really wants to take full advantage of the device (quad access) to speed up the overall boot process. This is on SoCFPGA btw.
Please allow me a few comments below.
Quoted 197 lines · Jagan Teki
Quoted 196 lines · Cyrille Pitchen
Le 15/03/2016 19:21, Jagan Teki a ?crit :
Quoted 38 lines · Cyrille Pitchen
Quoted 28 lines
Hi all,
This series of patches fixes and extend the support of QSPI memories in the SPI flash framework. The updates are split into many parts to make it easier to understand and review but they should be considered as a whole.
This was tested on a Atmel sama5d2 xplained board with a Micron n25q128a
memory.Best regards,
Cyrille
Cyrille Pitchen (18):
Revert "sf: Fix quad bit set for micron devices"
sf: callspi_claim_bus()andspi_release_bus()only once per read,
write or erase
sf: replacespi_flash_read_common()calls byspi_flash_cmd_read()
sf: removespi_flash_write_common()
sf: exportspi_flash_wait_ready()function
sf: share erase generic algorithm
sf: share write generic algorithm
sf: share read generic algorithm
sf: add hooks to handle register read and write operations
sf: move support of SST flash into genericspi_flash_write_alg()
sf: fix selection of supported READ commands for QSPI memoriesQuoted 8 lines
sf: fix detection of QSPI memories when they boot in Quad or
Dual mode
sf: add helper function to set the number of dummy bytes
sf: add 4byte address opcodes
sf: prepare next fixes to support of QSPI memories by manufacturer
sf: fix support of Micron memories
ARM: at91: clock: add function to get QSPI clocks
sf: add driver for Atmel QSPI controllerQuoted 8 lines
Appreciate for the work, we're working on spi-nor framework[1] planning to push in couple of weeks. Will let you know once it merged so that you can add your changes on top of that.
[1]
http://git.denx.de/?p=u-boot/u-boot-spi.git;a=shortlog;h=refs/heads/spi-nor-nextHi Jagan,
I've started to have a look on your branch. I hope it's not to late for few
comments:Globally I see the new code attend to match the spi-nor framework from Linux.
OK that's fine but please note the current spi-nor framework in Linux has incomplete and sometime not working support of QSPI memories.First, after a discussion with Brian and Bean on linux-mtd [1], Bean's commit
to add support to Micron QSPI memories was reverted since it didn't work alone.
In his reply, Brian agreed the code was not tested and should not have been
merged.This highlights a more general issue: currently, there is no mean for the spi-nor framework to notify the SPI controller driver about a SPI protocol
change at the QSPI memory side. This applies to Micron memories when they enter
their Quad I/O mode. If so, ALL commands, even JEDEC Read ID, Read Status Register, ..., MUST use the SPI 4-4-4 protocol. Commands sent using SPI 1-x-y
protocols are no longer decoded properly.
This also applies to Macronix and Winbond memories if they enter their QPI
mode, which is the equivalent of Micron Quad I/O mode.
This is why I've suggested to add 4 new fields in the structspi_nor:
- .reg_proto: the SPI protocol to be used by .read_reg() and .write_reg() hooks.
- .read_proto: the SPI protocol to be used by the .read() hooks, maybe by the
.read_mmap() also.
- .write_proto: the SPI protocol to be used by the .write() hooks
- .erase_proto: the SPI protocol to be used by the .erase() hooks.(Q)SPI controller drivers cannot guess the protocol to be used from the command
op code. Indeed, taking the Micron case as un example, the very same0xebop
code may be used with the SPI 1-4-4 protocol (Micron Extended SPI mode) or
with the SPI 4-4-4 protocol (Micron Quad I/O mode).Also just some words about the naming of SPI x-y-z protocols:
- x refers to the number of I/O lines used to send the op code byte
- y is the number of I/O lines used to send the address, mode/dummy cycles
(if these cycles exist for the command op code)
- z is the number of I/O lines used to send/receive data (if needed)So the
SNOR_OP_READ_1_1_2_IOmacro for the Fast Read Dual I/O command (as opposed to the macroSNOR_OP_READ_1_1_2macro for the Fast Read Dual Output
command) doesn't make sense: it should be namedSNOR_OP_READ_1_2_2.Then about the value used for the dummy cycles, it's not always true that we
don't care about initializing them. Depending on the configuration of the memory, some special dummy cycles, sometime called mode cycles, are used to
during Fast Read operations to make the memory enter/leaver its Continuous Read
mode. Once is Continuous Read mode, the op code byte is no longer sent, it is
implicit and the command actually starts from the address cycles. This mode
is mostly used for XIP applications hence is not relevant for mtd usage. However we should take care not to enter this Continuous Mode by mistake. Depending on the memory manufacturer, the Continuous Mode can be disabled by
updating the relevant bit in some configuration register (e.g. setting the XIP
bit in Micron Volatile Configuration Register) or by choosing the right op code
(e.g. for Winbond memories in QPI mode, both the0x0band0xebop codes can
be used for Fast Read 4-4-4 operation but only the0xebop code cares about
the dummy cycle value to enter/leave the Continuous Read mode). Some Spansion memories use 6 dummy cycles for Fast Read 1-4-4 command as factory default, not 8.Besides when sending a regular JEDEC Read ID (
0x9f) command to probe the (Q)SPI
memory, the current spi-nor framework assumes the Quad I/O or QPI mode is not
already enabled. This not always true, some early bootloarders, such as the
sama5d2 ROM Code, enables the Micron Quad I/O mode when configured to boot from
the QSPI memory. If so, the QSPI memory no longer replies to the0x9fcommand
in SPI 1-1-1 protocol but instead to the0xafcommand in SPI 4-4-4 protocol.Finally, about the proper way to describe the SPI controller capabilities,
the SPI_TX_{DUAL, QUAD} and SPI_RX_{DUAL, QUAD} mode flags are set in the SPI framework based on the "spi-rx-bus-width" and "spi-tx-bus-width" DT properties already used in Linux.
This is not enough to make the difference between the SPI 1-4-4 and SPI 4-4-4
protocols. Maybe some SPI controllers support the first protocol but not the
latest. It could be good to add another argument tospi_nor_scan()providing
an exhaustive list of SPI protocols supported by the SPI controller. Then to match this list with the list of SPI protocols supported by the SPI
memory and select the proper protocol, this new argument should use the same
range of values as the .flash_read field in the structspi_nor_infoused to
describe the SPI memories.For backward compatibility, the m25p80 driver could then convert the SPI modes
into spi-nor read modes. Please have a look at patch 11 of my series; the chunk related tospi_flash_probe_slave()insf_probe.c:/* Convert SPI mode_rx and mode to SPI flash read commands */(quoted diff) +16
-1+ mode_rx = spi->mode_rx; + if (mode_rx & SPI_RX_QUAD) { + e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST; + if (spi->mode & SPI_TX_QUAD) + e_rd_cmd |= QUAD_IO_FAST; + } else if (mode_rx & SPI_RX_DUAL) { + e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST; + if (spi->mode & SPI_TX_DUAL) + e_rd_cmd |= DUAL_IO_FAST; + } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) { + e_rd_cmd = ARRAY_SLOW; + } else { + e_rd_cmd = RD_NORM; + } + - ret = spi_flash_scan(flash); + ret = spi_flash_scan(flash, e_rd_cmd);Quoted 6 lines
Quoted 6 lines
I've spent a lot of time working on the QSPI memory topic so I can tell you
that there are many other traps to avoid!
If I can help you on this topic during your rework of the SPI NOR support,
please let me know.Thanks Cyrille, for this very detailed and good explanation. This is really appreciated. And I really hope that Jagan will get back to your generous offer, to assist with any such QSPI NOR related problems. I'll definitely remember this and might bug you at some time... ;)
Quoted 8 lines
I understand your points, thanks for that and anyway this spi-nor work is a starting point for both syncing with Linux as well with new feature or for better tunning. And more over I started this work in 2014 end and it's been reviewing over and over and we finally landed up with MTD driver model.
So, please wait for sometime until this gets merged we definitely work together for better tunning, thanks!
Jagan, what is the current plan here? I have to admit that I didn't check closely on your SPI-NOR work lately, sorry. So I can't really comment with a profound deep knowledge. But from what I read in Cyrille's patchset and explanation above, his patchset fixes some issues and brings us also more in line with the (upcoming) Linux framework. So I would really love to see this integrated into mainline quickly. Allowing a broader test basis on multiple platforms. Will it be a big task for Cyrille to rebase his patchset on top of your patches? Can you perhaps assist Cyrille with this? Or would it perhaps make sense to postpone your patchset and integrate Cyrille's first instead?
Quoted 4 lines
Cyrille, if Jagans rework goes in first, do you already have a plan on when to rebase your patchset on top of this? Or do you see some "show-stoppers" here?
Well if I need to rebase my patchset, for sure I will wait for Jagan's rework to be completed and accepted first. I don't think it would be efficient to rebase the QSPI series on the fly before the rework is totally stabilized.
Quoted 6 lines
One of the commit message from u-boot-spi.git can sum up the global rework:
"sf: Drop entire spi-flash framework" [1]Indeed all files from
drivers/mtd/spiare deleted, the next commits replace them by new files in the spi-nor folder. These new files are almost some "copy/paste" ofdrivers/mtd/spi-norfiles from Linux.Yeah.. the idea of using Linux spi-nor is like u-boot also facing similar issue where Linux facing like spi drivers became more flash centric, and it's not totally same design as Linux. We took the idea from Linux and have MTD driver model on top of it. The whole idea to add this is to follow the u-boot driver model principle and if the stack look some how similar to Linux then the development is as faster as, when
compared to maintain separate thread of development - this is very legacy story I have been saying on this on ML for year back.
Quoted 2 lines
And did you find any issues with this spi-nor series?
Well, the spi-nor series is based on Linux code, which already lacks support of QSPI memories.
Moreover, the Linux version of m25p80.c uses the tx_nbits and rx_bits fields of the struct spi_transfer to tell the SPI controller driver about the number of I/O lines to be used to send or receive the command bytes. However there is no equivalent mechanism with the u-boot version which relies on calls of spi_write_then_read(). The u-boot version has no mean to support SPI protocols other than SPI 1-1-1 and the SPI controller drivers should not try to guess the SPI protocol from the op code.
Also be aware that the design chosen by the Linux m25p80 driver, that is to say the use of spi_sync_transfer() or spi_sync(), is not suited to all hardware QSPI controllers. For instance the Atmel QSPI controller expects separated inputs for the command op code, the address, the dummy cycles and the data.
spi_write_then_read() calls spi_xfer() twice: the first time to send the op code, address and dummy cycles then the second time to send the data. How can a SPI controller driver make the difference between the two calls if it should decode the input buffer to extract the op code, the address then the dummy cycles on the first call but send raw data for the second call?
In addition, maybe it could be better to call spi_claim_bus() / spi_release_bus() once for all at the beginning / end of spi_nor_read(), spi_nor_erase() and spi_nor_write() instead of calling them for each register read/write operation. I would avoid so many calls.
About the support the 16MiB memories, I see that commit 795c078c4563 ("mtd: spi-nor: Add 4-byte addressing") copies the Linux version except for the special case of Spansion memories which uses the dedicated 4byte address op codes for Fast Read, Page Program and Sector Erase.
Please note that entering the 4byte address mode, like set_4byte() does, changes the internal state of the SPI memory which has side effects: if a CPU reset occurs and if early bootloaders don't support this address mode, sending only 3 address bytes inside Fast Read commands, they fail reading from the SPI memory. That's why I've sent a patch to implement an alternative (thus optional) method to support >16MiB memories by converting the 3byte address op codes to their associated 4byte version:
0x02 -> 0x12 Page Program 0x03 -> 0x13 Read 0x0b -> 0x0c Fast Read 0x6b -> 0x6c Fast Read Quad Output 1-1-4 0xd8 -> 0xdc Sector Erase
...
Quoted 21 lines
Quoted 6 lines
OK, why not but it also implies that I can't simply rebase my patchset. Since the all files are different it means I have to write a new series of patches from scratch. As I said, I won't start such a work before the new framework is totally accepted and integrated in next releases of u-boot.
Quoted 14 lines
I don't say using the Linux code as a reference is a bad idea, indeed there are good things in the spi-nor framework to be taken. For instance, in my own series I added .read_reg() and .write_reg() hooks the same way as done in the Linux source.
I just warn developers that currently the Linux code misses some stuff to support QSPI memories efficiently. As an example,spi_nor_scan()fails to read the JEDEC ID if the QSPI memory is already in QPI mode (Micron, Macronix, Winbond, ...).
This issue didn't exist with regular SPI NOR flash memories as they are almost "stateless" as compared to QSPI memories. SPI memories always use a single protocol, SPI 1-1-1 with MISO and MOSI I/O lines, for all commands. On the other hand, QSPI memories are much complex: you have to deal with many different protocols and find a way to guess the current internal state of the QSPI memory before sending commands to it.
Quoted 6 lines
OK, I understand that you sent separate patches, are these patches fix this issue?
https://patchwork.ozlabs.org/patch/598527/
https://patchwork.ozlabs.org/patch/598528/
https://patchwork.ozlabs.org/patch/598530/
Those 3 patches only deal with support of the sama5d2 xplained board. They prepare the migration to the DM model and DT support since the Atmel QSPI controller driver uses the DM model. One of them also configures the pin muxing as needed to use the QSPI controller.
They are Work In Progress and not related with the mtd sub-system. I only provide them to unblock some customers who are waiting for support of QSPI memories in u-boot on sama5d2 SoCs.
Quoted 1 line
I guess this last one is not related with the mtd sub-system itself. It fixes an issue I found using the "sf probe" command. However it might need some review because I don't understand why the "device_unbind(new)" call was there at first so maybe I miss something. I guess there was a good reason to add this call and I want to avoid introducing regression.
Quoted 6 lines
If so, then I will start reviewing these and will push these changes first and will rebase spi-nor on top of this.
thanks!
Best regards,
Cyrille