sf: improve support of (Q)SPI flash memories
v2 cover sf: improve support of (Q)SPI flash memories
This series of patches are based and have been tested on the 'master' branch of the u-boot.git tree.
Tests were passed with a sama5d2 xplained board which embeds both SPI and QSPI controllers.
The following tests have been passed:
- QSPI0 + Macronix MX25L25673G:
+ probe: OK
+ Fast Read 1-1-4 at offset 0x10000 (u-boot env): OK
+ Page Program 1-1-4 at offset 0x10000: OK
The Macronix datasheet tells that only Page Program 1-4-4 is supported, not Page Program 1-1-4, however it worked, I don't know why...
- QSPI0 + Microchip SST26
+ probe: OK
+ Fast Read 1-1-4 at offset 0x10000 (u-boot env): OK
+ Page Program 1-1-1 at offset 0x10000: OK
SST26 memories support Page Program 1-4-4 but with the op code of Page Program 1-1-4, which is not standard so I don't use it.
- QSPI0 + Adesto AT25DF321A
+ probe: OK
+ Fast Read 1-1-1 at offset 0x10000 (u-boot env): OK
+ Page Program 1-1-1 at offset 0x10000: OK
- SPI0 + Adesto AT25DF321A
+ probe: OK
+ Fast Read 1-1-1 at offset 0x6000 (u-boot env): OK
+ Page Program 1-1-1 at offest 0x6000: OK
- SPI1 + Atmel AT45
+ probe: OK
+ Read at offset 0 and other than 0: OK
+ Write at offset 0 and other than 0: OK
During my tests, I used:
- setenv/saveenv, reboot, printenv
or
- sf probe, sf read, sf write, sf erase and sf update.
Changes in v2:
- Rebase on the latest u-boot/master(2710d54f5).
Cyrille Pitchen (8):
spi: add support of SPI flash commands
sf: describe all SPI flash commands with 'struct spi_flash_command'
sf: select the relevant SPI flash protocol for read and write commands
sf: differentiate Page Program 1-1-4 and 1-4-4
sf: add 'addr_len' member to 'struct spi_flash'
sf: add new option to support SPI flash above 16MiB
sf: add support to Microchip SST26 QSPI memories
sf: add driver for Atmel QSPI controller
drivers/mtd/spi/Kconfig | 16 +- drivers/mtd/spi/sf.c | 78 ++++++-- drivers/mtd/spi/sf_dataflash.c | 119 ++++++------ drivers/mtd/spi/sf_internal.h | 48 +++-- drivers/mtd/spi/spi_flash.c | 341 +++++++++++++++++++++++---------- drivers/mtd/spi/spi_flash_ids.c | 5 + drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/atmel_qspi.c | 404 ++++++++++++++++++++++++++++++++++++++++ drivers/spi/atmel_qspi.h | 169 +++++++++++++++++ drivers/spi/spi-uclass.c | 40 ++++ drivers/spi/spi.c | 13 ++ include/spi.h | 168 +++++++++++++++++ include/spi_flash.h | 6 + 14 files changed, 1225 insertions(+), 190 deletions(-) create mode 100644 drivers/spi/atmel_qspi.c create mode 100644 drivers/spi/atmel_qspi.h
Signature · 1 line
2.13.0
PATCH v2 1/8 spi: add support of SPI flash commands
From: Cyrille Pitchen <[email protected]>
This patch introduces 'struct spi_flash_command' and functions spi_is_flash_command_supported() / spi_exec_flash_command().
The 'struct spi_flash_command' describes all the relevant parameters to execute any SPI flash command:
- the instruction op code
- the number of bytes used to send the address: 0, 3 or 4 bytes
- the number of mode and wait-state clock cycles, also called dummy cycles
- the number and values of data bytes to be sent or received
- the SPI x-y-z protocol [1]
- the flash command type [2]
[1] SPI x-y-z protocol:
- x is the number of I/O lines used to send the instruction op code.
- y is the number of I/O lines used during address, mode and wait-state clock cycles.
- z is the number of I/O lines used to send or received data.
[2] Flash command type:
The flash command type is provided to differenciate "memory" read/write/erase operations from "flash internal register" read/write operations. Indeed some SPI controller drivers handle those command type in different ways.
However SPI controller drivers should not check the value of the instruction op code to guess the actual kind of flash command to perform. Many instruction op codes are SPI flash manufacturer specific and only drivers/mtd/spi/spi_flash.c should have the knowledge of all of them.
Besides, more and more QSPI controllers, like those of TI and Candence, have special way to support (Fast) Read operations using some "memory like" area mapped into the system bus. Hence, if those drivers choose to override the default implementation of spi_is_flash_command_supported() so that their own functions return true only for a "memory read" flash command type, then spi_exec_flash_command() might be used to implement the read from the "memory like" area mapped into the system bus.
It means that spi_exec_flash_command() could be used to supersede the actual flash->memory_map mechanism; spi_is_flash_command_supported() / spi_exec_flash_command() being more generic and covering more use cases.
For instance, the Atmel QSPI hardware controller uses its "memory like" area mapped ino the system to perform not only (Fast) Read operations but actually all other types of flash commands. Hence the regular SPI API based on the spi_xfer() function is not suited to support the Atmel QSPI controller.
---
Changes in v2: None
drivers/spi/spi-uclass.c | 40 +++++++++++ drivers/spi/spi.c | 13 ++++ include/spi.h | 168 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+)
drivers/spi/spi-uclass.c +40 -0
@@ -91,6 +91,30 @@ int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,return spi_get_ops (bus)->xfer (dev, bitlen, dout, din, flags); } +bool dm_spi_is_flash_command_supported (struct udevice *dev, +const struct spi_flash_command *cmd) +{ +struct udevice *bus = dev->parent; +struct dm_spi_ops *ops =spi_get_ops (bus); + +if (ops->is_flash_command_supported) +return ops->is_flash_command_supported (dev, cmd); + +return false; +} + +int dm_spi_exec_flash_command (struct udevice *dev, +const struct spi_flash_command *cmd) +{ +struct udevice *bus = dev->parent; +struct dm_spi_ops *ops =spi_get_ops (bus); + +if (ops->exec_flash_command) +return ops->exec_flash_command (dev, cmd); + +return -EINVAL ; +} +int spi_claim_bus (struct spi_slave *slave) {return dm_spi_claim_bus (slave->dev);
@@ -107,6 +131,18 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,return dm_spi_xfer (slave->dev, bitlen, dout, din, flags); } +bool spi_is_flash_command_supported (struct spi_slave *slave, +const struct spi_flash_command *cmd) +{ +return dm_spi_is_flash_command_supported (slave->dev, cmd); +} + +int spi_exec_flash_command (struct spi_slave *slave, +const struct spi_flash_command *cmd) +{ +return dm_spi_exec_flash_command (slave->dev, cmd); +} +#if !CONFIG_IS_ENABLED (OF_PLATDATA )static int spi_child_post_bind (struct udevice *dev) {
@@ -144,6 +180,10 @@ static int spi_post_probe(struct udevice *bus) ops->set_mode += gd->reloc_off;if (ops->cs_info) ops->cs_info += gd->reloc_off; +if (ops->is_flash_command_supported) + ops->is_flash_command_supported += gd->reloc_off; +if (ops->exec_flash_command) + ops->exec_flash_command += gd->reloc_off;#endif return 0 ;
drivers/spi/spi.c +13 -0
@@ -5,6 +5,7 @@*/ #include <common.h> +#include <errno.h> #include <fdtdec.h> #include <malloc.h> #include <spi.h>
@@ -58,3 +59,15 @@ struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum, return spi_setup_slave(busnum, cs, max_hz, mode); }#endif + +__weak bool spi_is_flash_command_supported (struct spi_slave *slave, +const struct spi_flash_command *cmd) +{ +return false; +} + +__weak int spi_exec_flash_command (struct spi_slave *slave, +const struct spi_flash_command *cmd) +{ +return -EINVAL ; +}
include/spi.h +168 -0
198 lines not on this page · raw message
Signature · 1 line
2.13.0
PATCH v2 2/8 sf: describe all SPI flash commands with 'struct spi_flash_command'
In reply to Wenyou YangFrom: Cyrille Pitchen <[email protected]>
Now that the SPI sub-system API has been extended with 'struct spi_flash_command' and spi_is_flash_command_supported() / spi_exec_flash_command() functions, we update the SPI FLASH sub-system to use this new API.
---
Changes in v2: None
drivers/mtd/spi/sf.c | 78 +++++++++++++---- drivers/mtd/spi/sf_dataflash.c | 119 +++++++++++++------------- drivers/mtd/spi/sf_internal.h | 24 +++--- drivers/mtd/spi/spi_flash.c | 184 +++++++++++++++++++++++------------------ 4 files changed, 236 insertions(+), 169 deletions(-)
drivers/mtd/spi/sf.c +60 -18
@@ -9,46 +9,88 @@#include <common.h> #include <spi.h> +#include <spi_flash.h> -static int spi_flash_read_write (struct spi_slave *spi, -const u8 *cmd,size_t cmd_len, -const u8 *data_out,u8 *data_in, -size_t data_len) +#include "sf_internal.h" + +static void spi_flash_addr (u32 addr,u8 addr_len,u8 *cmd_buf) { +u8 i; + +for (i =0 ; i < addr_len; i++) + cmd_buf[i] = addr >> ((addr_len -1 - i) *8 ); +} + +static u8 spi_compute_num_dummy_bytes (enum spi_flash_protocol proto, +u8 num_dummy_clock_cycles) +{ +int shift =fls (spi_flash_protocol_get_addr_nbits (proto)) -1 ; + +if (shift <0 ) + shift =0 ; +return (num_dummy_clock_cycles << shift) >>3 ; +} + +static int spi_flash_exec (struct spi_flash *flash, +const struct spi_flash_command *cmd) +{ +struct spi_slave *spi = flash->spi; +u8 cmd_buf[SPI_FLASH_CMD_LEN ]; +size_t cmd_len, num_dummy_bytes;unsigned long flags =SPI_XFER_BEGIN ;int ret; -if (data_len ==0 ) +if (spi_is_flash_command_supported (spi, cmd)) +return spi_exec_flash_command (spi, cmd); + +if (cmd->data_len ==0 ) flags |=SPI_XFER_END ; - ret =spi_xfer (spi, cmd_len *8 , cmd,NULL , flags); + cmd_buf[0 ] = cmd->inst; +spi_flash_addr (cmd->addr, cmd->addr_len, cmd_buf +1 ); + cmd_len =1 + cmd->addr_len; + + num_dummy_bytes =spi_compute_num_dummy_bytes (cmd->proto, + cmd->num_mode_cycles + + cmd->num_wait_states); +memset (cmd_buf + cmd_len,0xff , num_dummy_bytes); + cmd_len += num_dummy_bytes; + + ret =spi_xfer (spi, cmd_len *8 , cmd_buf,NULL , flags);if (ret) {debug ("SF: Failed to send command (%zu bytes): %d\n" , cmd_len, ret); - }else if (data_len !=0 ) { - ret =spi_xfer (spi, data_len *8 , data_out, data_in, -SPI_XFER_END ); + }else if (cmd->data_len !=0 ) { + ret =spi_xfer (spi, cmd->data_len *8 , + cmd->tx_data, cmd->rx_data, +SPI_XFER_END );if (ret)debug ("SF: Failed to transfer %zu bytes of data: %d\n" , - data_len, ret); + cmd->data_len, ret); }return ret; } -int spi_flash_cmd_read (struct spi_slave *spi,const u8 *cmd, -size_t cmd_len,void *data,size_t data_len) +int spi_flash_cmd_read (struct spi_flash *flash, +const struct spi_flash_command *cmd) { -return spi_flash_read_write (spi, cmd, cmd_len,NULL , data, data_len); +return spi_flash_exec (flash, cmd); } -int spi_flash_cmd (struct spi_slave *spi,u8 cmd,void *response,size_t len) +int spi_flash_cmd (struct spi_flash *flash,u8 instr,void *response,size_t len) { -return spi_flash_cmd_read (spi, &cmd,1 , response, len); +struct spi_flash_command cmd; +u8 flags = (response && len) ?SPI_FCMD_READ_REG :SPI_FCMD_WRITE_REG ; + +spi_flash_command_init (&cmd, instr,0 , flags); + cmd.data_len = len; + cmd.rx_data = response; +return spi_flash_exec (flash, &cmd); } -int spi_flash_cmd_write (struct spi_slave *spi,const u8 *cmd,size_t cmd_len, -const void *data,size_t data_len) +int spi_flash_cmd_write (struct spi_flash *flash, +const struct spi_flash_command *cmd) { -return spi_flash_read_write (spi, cmd, cmd_len, data,NULL , data_len); +return spi_flash_exec (flash, cmd); }
drivers/mtd/spi/sf_dataflash.c +61 -58
294 lines not on this page · raw message
drivers/mtd/spi/sf_internal.h +12 -12
@@ -27,7 +27,7 @@ enum spi_nor_option_flags { };#define SPI_FLASH_3B_ADDR_LEN 3 -#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) +#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN + 16)#define SPI_FLASH_16MB_BOUN 0x1000000/* CFI Manufacture ID's */
@@ -137,21 +137,21 @@ struct spi_flash_info {extern const struct spi_flash_info spi_flash_ids[];/* Send a single-byte command to the device and read the response */ -int spi_flash_cmd (struct spi_slave *spi,u8 cmd,void *response,size_t len); +int spi_flash_cmd (struct spi_flash *flash,u8 instr,void *response,size_t len);/* * Send a multi-byte command to the device and read the response. Used * for flash array reads, etc. */ -int spi_flash_cmd_read (struct spi_slave *spi,const u8 *cmd, -size_t cmd_len,void *data,size_t data_len); +int spi_flash_cmd_read (struct spi_flash *flash, +const struct spi_flash_command *cmd);/* * Send a multi-byte command to the device followed by (optional) * data. Used for programming the flash array, etc. */ -int spi_flash_cmd_write (struct spi_slave *spi,const u8 *cmd,size_t cmd_len, -const void *data,size_t data_len); +int spi_flash_cmd_write (struct spi_flash *flash, +const struct spi_flash_command *cmd);/* Flash erase(sectors) operation, support all possible erase commands */
@@ -169,13 +169,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_cmd (flash,CMD_WRITE_ENABLE ,NULL ,0 ); }/* 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_cmd (flash,CMD_WRITE_DISABLE ,NULL ,0 ); }/*
@@ -186,8 +186,8 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)* - spi_flash_wait_till_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); +int spi_flash_write_common (struct spi_flash *flash, +const struct spi_flash_command *cmd);/* * Flash write operation, support all possible write commands.
@@ -201,8 +201,8 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,* Same as spi_flash_cmd_read() except it also claims/releases the SPI * bus. 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); +int spi_flash_read_common (struct spi_flash *flash, +const struct spi_flash_command *cmd);/* Flash read operation, support all possible read commands */ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
drivers/mtd/spi/spi_flash.c +103 -81
397 lines not on this page · raw message
Signature · 1 line
2.13.0
PATCH v2 3/8 sf: select the relevant SPI flash protocol for read and write commands
In reply to Wenyou YangFrom: Cyrille Pitchen <[email protected]>
SPI controller drivers should not check the instruction op code byte to guess which SPI x-y-z protocol is to be used for Fast Read or Page Program operations.
Indeed, the op code values are not so reliable. For instance, the 32h op code is generally used for Page Program 1-1-4 operations. However Microchip SST26 memories use this 32h op code for their Page Program 1-4-4 operations. There are many other examples of those SPI flash manufacturer quirks.
Instead, the SPI FLASH sub-system now fills the 'proto' member of 'struct spi_flash_command' with flash->read_proto for Fast Read operations and flash->write_proto for Page Program operations.
---
Changes in v2: None
drivers/mtd/spi/spi_flash.c | 24 ++++++++++++++++-------- include/spi_flash.h | 4 ++++ 2 files changed, 20 insertions(+), 8 deletions(-)
drivers/mtd/spi/spi_flash.c +16 -8
@@ -379,6 +379,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,spi_flash_command_init (&cmd, flash->write_cmd,SPI_FLASH_3B_ADDR_LEN ,SPI_FCMD_WRITE ); + cmd.proto = flash->write_proto;for (actual =0 ; actual < len; actual += chunk_len) { write_addr = offset;
@@ -482,6 +483,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,spi_flash_command_init (&cmd, flash->read_cmd,SPI_FLASH_3B_ADDR_LEN ,SPI_FCMD_READ ); + cmd.proto = flash->read_proto; cmd.num_wait_states = flash->dummy_byte *8 ;while (len) { read_addr = offset;
@@ -1044,24 +1046,30 @@ int spi_flash_scan(struct spi_flash *flash)/* Look for read commands */ flash->read_cmd =CMD_READ_ARRAY_FAST ; -if (spi->mode &SPI_RX_SLOW ) + flash->read_proto =SPI_FPROTO_1_1_1 ; +if (spi->mode &SPI_RX_SLOW ) { flash->read_cmd =CMD_READ_ARRAY_SLOW ; -else if (spi->mode &SPI_RX_QUAD && info->flags &RD_QUAD ) + }else if (spi->mode &SPI_RX_QUAD && info->flags &RD_QUAD ) { flash->read_cmd =CMD_READ_QUAD_OUTPUT_FAST ; -else if (spi->mode &SPI_RX_DUAL && info->flags &RD_DUAL ) + flash->read_proto =SPI_FPROTO_1_1_4 ; + }else if (spi->mode &SPI_RX_DUAL && info->flags &RD_DUAL ) { flash->read_cmd =CMD_READ_DUAL_OUTPUT_FAST ; + flash->read_proto =SPI_FPROTO_1_1_2 ; + }/* Look for write commands */ -if (info->flags &WR_QPP && spi->mode &SPI_TX_QUAD ) +if (info->flags &WR_QPP && spi->mode &SPI_TX_QUAD ) { flash->write_cmd =CMD_QUAD_PAGE_PROGRAM ; -else + flash->write_proto =SPI_FPROTO_1_1_4 ; + }else {/* Go for default supported write cmd */ flash->write_cmd =CMD_PAGE_PROGRAM ; + flash->write_proto =SPI_FPROTO_1_1_1 ; + }/* 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 )) { +if (spi_flash_protocol_get_data_nbits (flash->read_proto) ==4 || +spi_flash_protocol_get_data_nbits (flash->write_proto) ==4 ) { ret =set_quad_mode (flash, info);if (ret) { debug("SF: Fail to set QEB for %02x\n",
include/spi_flash.h +4 -0
@@ -48,6 +48,8 @@ struct spi_slave;* @read_cmd: Read cmd - Array Fast, Extn read and quad read. * @write_cmd: Write cmd - page and quad program. * @dummy_byte: Dummy cycles for read operation. +* @read_proto: SPI x-y-z protocol for flash read ops +* @write_proto: SPI x-y-z protocol for flash write ops * @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
@@ -83,6 +85,8 @@ struct spi_flash {u8 read_cmd;u8 write_cmd;u8 dummy_byte; +enum spi_flash_protocol read_proto; +enum spi_flash_protocol write_proto;void *memory_map;
Signature · 1 line
2.13.0
PATCH v2 4/8 sf: differentiate Page Program 1-1-4 and 1-4-4
In reply to Wenyou YangFrom: Cyrille Pitchen <[email protected]>
This patch simply renames the ambiguous CMD_QUAD_PAGE_PROGRAM macro into the more explicit CMD_PAGE_PROGRAM_1_1_4.
Also it defines the CMD_PAGE_PROGRAM_1_4_4 macro to the standard 38h op code.
---
Changes in v2: None
drivers/mtd/spi/sf_internal.h | 3 ++- drivers/mtd/spi/spi_flash.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/mtd/spi/sf_internal.h +2 -1
@@ -48,7 +48,8 @@ enum spi_nor_option_flags {#define CMD_PAGE_PROGRAM 0x02#define CMD_WRITE_DISABLE 0x04#define CMD_WRITE_ENABLE 0x06 -#define CMD_QUAD_PAGE_PROGRAM 0x32 +#define CMD_PAGE_PROGRAM_1_1_4 0x32 +#define CMD_PAGE_PROGRAM_1_4_4 0x38/* Read commands */ #define CMD_READ_ARRAY_SLOW 0x03
drivers/mtd/spi/spi_flash.c +1 -1
@@ -1059,7 +1059,7 @@ int spi_flash_scan(struct spi_flash *flash)/* Look for write commands */ if (info->flags &WR_QPP && spi->mode &SPI_TX_QUAD ) { - flash->write_cmd =CMD_QUAD_PAGE_PROGRAM ; + flash->write_cmd =CMD_PAGE_PROGRAM_1_1_4 ; flash->write_proto =SPI_FPROTO_1_1_4 ; }else {/* Go for default supported write cmd */
Signature · 1 line
2.13.0
PATCH v2 5/8 sf: add 'addr_len' member to 'struct spi_flash'
In reply to Wenyou YangFrom: Cyrille Pitchen <[email protected]>
This is a transitional patch to prepare the SPI FLASH sub-system to support the 4-byte address instruction set later.
For now, flash->addr_len is always set to SPI_FLASH_3B_ADDR_LEN.
---
Changes in v2: None
drivers/mtd/spi/spi_flash.c | 13 ++++++++----- include/spi_flash.h | 2 ++ 2 files changed, 10 insertions(+), 5 deletions(-)
drivers/mtd/spi/spi_flash.c +8 -5
@@ -322,7 +322,7 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) } } -spi_flash_command_init (&cmd, flash->erase_cmd,SPI_FLASH_3B_ADDR_LEN , +spi_flash_command_init (&cmd, flash->erase_cmd, flash->addr_len,SPI_FCMD_ERASE );while (len) { erase_addr = offset;
@@ -377,7 +377,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, } } -spi_flash_command_init (&cmd, flash->write_cmd,SPI_FLASH_3B_ADDR_LEN , +spi_flash_command_init (&cmd, flash->write_cmd, flash->addr_len,SPI_FCMD_WRITE ); cmd.proto = flash->write_proto;for (actual =0 ; actual < len; actual += chunk_len) {
@@ -481,7 +481,7 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,return 0 ; } -spi_flash_command_init (&cmd, flash->read_cmd,SPI_FLASH_3B_ADDR_LEN , +spi_flash_command_init (&cmd, flash->read_cmd, flash->addr_len,SPI_FCMD_READ ); cmd.proto = flash->read_proto; cmd.num_wait_states = flash->dummy_byte *8 ;
@@ -529,7 +529,7 @@ static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)int ret;u8 sr =0xFFu ; -spi_flash_command_init (&cmd,CMD_SST_BP ,SPI_FLASH_3B_ADDR_LEN , +spi_flash_command_init (&cmd,CMD_SST_BP , flash->addr_len,SPI_FCMD_WRITE ); cmd.addr = offset; cmd.data_len =1 ;
@@ -580,7 +580,7 @@ int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,if (ret) goto done; -spi_flash_command_init (&cmd,CMD_SST_AAI_WP ,SPI_FLASH_3B_ADDR_LEN , +spi_flash_command_init (&cmd,CMD_SST_AAI_WP , flash->addr_len,SPI_FCMD_WRITE ); cmd.addr = offset; cmd.data_len =2 ;
@@ -1102,6 +1102,9 @@ int spi_flash_scan(struct spi_flash *flash) flash->flags |=SNOR_F_USE_FSR ;#endif +/* Set the address length */ + flash->addr_len =SPI_FLASH_3B_ADDR_LEN ; +/* Configure the BAR - discover bank cmds and read current bank */ #ifdef CONFIG_SPI_FLASH_BAR ret =read_bar (flash, info);
include/spi_flash.h +2 -0
@@ -44,6 +44,7 @@ struct spi_slave;* @bank_read_cmd: Bank read cmd * @bank_write_cmd: Bank write cmd * @bank_curr: Current flash bank +* @addr_len: Number of bytes for the address * @erase_cmd: Erase cmd 4K, 32K, 64K * @read_cmd: Read cmd - Array Fast, Extn read and quad read. * @write_cmd: Write cmd - page and quad program.
@@ -81,6 +82,7 @@ struct spi_flash {u8 bank_write_cmd;u8 bank_curr;#endif +u8 addr_len;u8 erase_cmd;u8 read_cmd;u8 write_cmd;
Signature · 1 line
2.13.0
PATCH v2 6/8 sf: add new option to support SPI flash above 16MiB
In reply to Wenyou YangFrom: Cyrille Pitchen <[email protected]>
The patch provides an alternative method to support SPI flash size greater than 16MiB (128Mib).
Indeed using the Base Address Register (BAR) is stateful. Hence, once the BAR has been modified, if a spurious CPU reset occurs with no reset/power off at the SPI flash side, early boot loarders may try to read from offset 0 but fails because of the new BAR value.
On the other hand, using the 4-byte address instruction set is stateless. When supported by the SPI flash memory, it allows us to access memory data area above 16MiB without changing the internal state of this SPI flash memory. Then if a spirious reboot occurs, early boot loaders can still access data from offset 0.
---
Changes in v2: None
drivers/mtd/spi/Kconfig | 16 +++++++- drivers/mtd/spi/sf_internal.h | 18 +++++++++ drivers/mtd/spi/spi_flash.c | 92 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 119 insertions(+), 7 deletions(-)
drivers/mtd/spi/Kconfig +15 -1
@@ -34,14 +34,28 @@ config SPI_FLASH If unsure, say N +choice + prompt "Support SPI flash above 16MiB" + depends on SPI_FLASH + optional + 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_4BAIS + bool "SPI flash 4-byte address instruction set support" + help + Convert the selected 3-byte address op codes into their associated + 4-byte address op codes. Using this instruction set does not change + the internal state of the SPI flash device. + +endchoice + + config SF_DUAL_FLASH bool "SPI DUAL flash memory support" depends on SPI_FLASH
drivers/mtd/spi/sf_internal.h +18 -0
@@ -27,6 +27,7 @@ enum spi_nor_option_flags { };#define SPI_FLASH_3B_ADDR_LEN 3 +#define SPI_FLASH_4B_ADDR_LEN 4#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN + 16)#define SPI_FLASH_16MB_BOUN 0x1000000
@@ -64,6 +65,19 @@ enum spi_nor_option_flags {#define CMD_READ_CONFIG 0x35#define CMD_FLAG_STATUS 0x70 +/* 4-byte address instruction set */ +#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_PAGE_PROGRAM_4B 0x12 +#define CMD_PAGE_PROGRAM_1_1_4_4B 0x34 +#define CMD_PAGE_PROGRAM_1_4_4_4B 0x3e +#define CMD_ERASE_4K_4B 0x21 +#define CMD_ERASE_64K_4B 0xdc +/* Bank addr access commands */ #ifdef CONFIG_SPI_FLASH_BAR # define CMD_BANKADDR_BRWR 0x17
@@ -133,6 +147,10 @@ struct spi_flash_info {#define RD_QUADIO BIT(6)/* use Quad IO Read */ #define RD_DUALIO BIT(7)/* use Dual IO Read */ #define RD_FULL (RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO) +#define NO_4BAIS BIT(8)/* +* 4-byte address instruction set +* NOT supported +*/ };extern const struct spi_flash_info spi_flash_ids[];
drivers/mtd/spi/spi_flash.c +86 -6
117 lines not on this page · raw message
Signature · 1 line
2.13.0
PATCH v2 7/8 sf: add support to Microchip SST26 QSPI memories
In reply to Wenyou YangFrom: Cyrille Pitchen <[email protected]>
This patch adds support to Microchip SST26 QSPI memories.
Erase blocks are protected at power up and must be unlocked first before being erased then programmed.
Also, the erase block sizes are not uniform. The memory layout is uniform only for the 4K sector blocks. The 64K Block Erase (D8h) op code cannot be used as currently done by the SPI FLASH sub-system.
The 4K Sector Erase (20h) op code should be chosen instead even if CONFIG_SPI_FLASH_USE_4K_SECTORS is not set.
---
Changes in v2: None
drivers/mtd/spi/sf_internal.h | 3 +++ drivers/mtd/spi/spi_flash.c | 36 ++++++++++++++++++++++++++++++++---- drivers/mtd/spi/spi_flash_ids.c | 5 +++++ 3 files changed, 40 insertions(+), 4 deletions(-)
drivers/mtd/spi/sf_internal.h +3 -0
@@ -104,6 +104,7 @@ 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 */ +# define CMD_SST_ULBPR 0x98/* Global Block Protection Unlock */ int sst_write_wp (struct spi_flash *flash,u32 offset,size_t len,const void *buf);
@@ -151,6 +152,8 @@ struct spi_flash_info {* 4-byte address instruction set * NOT supported */ +#define SECT_4K_ONLY BIT(9)/* use only CMD_ERASE_4K */ +#define SST_ULBPR BIT(10)/* use SST unlock block protection */ };extern const struct spi_flash_info spi_flash_ids[];
drivers/mtd/spi/spi_flash.c +32 -4
@@ -73,7 +73,8 @@ static int write_sr(struct spi_flash *flash, u8 ws)return 0 ; } -#if defined(CONFIG_SPI_FLASH_SPANSION ) || defined(CONFIG_SPI_FLASH_WINBOND ) +#if defined(CONFIG_SPI_FLASH_SPANSION ) || defined(CONFIG_SPI_FLASH_WINBOND ) || \ + defined(CONFIG_SPI_FLASH_SST )static int read_cr (struct spi_flash *flash,u8 *rc) {struct spi_flash_command cmd;
@@ -891,6 +892,22 @@ int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) }#endif +#ifdef CONFIG_SPI_FLASH_SST +static int sst26_unlock (struct spi_flash *flash) +{ +struct spi_flash_command cmd; +int ret; + +spi_flash_command_init (&cmd,CMD_SST_ULBPR ,0 ,SPI_FCMD_WRITE_REG ); + ret =spi_flash_write_common (flash, &cmd); +if (ret) { +debug ("SF: SST26 is still locked (read-only)\n" ); +return ret; + } + +return 0 ; +} +#endif #ifdef CONFIG_SPI_FLASH_MACRONIX static int macronix_quad_enable (struct spi_flash *flash)
@@ -920,7 +937,8 @@ static int macronix_quad_enable(struct spi_flash *flash) }#endif -#if defined(CONFIG_SPI_FLASH_SPANSION ) || defined(CONFIG_SPI_FLASH_WINBOND ) +#if defined(CONFIG_SPI_FLASH_SPANSION ) || defined(CONFIG_SPI_FLASH_WINBOND ) ||\ + defined(CONFIG_SPI_FLASH_SST )static int spansion_quad_enable (struct spi_flash *flash) {u8 qeb_status;
@@ -981,9 +999,11 @@ static int set_quad_mode(struct spi_flash *flash,case SPI_FLASH_CFI_MFR_MACRONIX :return macronix_quad_enable (flash);#endif -#if defined(CONFIG_SPI_FLASH_SPANSION ) || defined(CONFIG_SPI_FLASH_WINBOND ) +#if defined(CONFIG_SPI_FLASH_SPANSION ) || defined(CONFIG_SPI_FLASH_WINBOND ) ||\ + defined(CONFIG_SPI_FLASH_SST )case SPI_FLASH_CFI_MFR_SPANSION :case SPI_FLASH_CFI_MFR_WINBOND : +case SPI_FLASH_CFI_MFR_SST :return spansion_quad_enable (flash);#endif #ifdef CONFIG_SPI_FLASH_STMICRO
@@ -1039,6 +1059,11 @@ int spi_flash_scan(struct spi_flash *flash) JEDEC_MFR(info) == SPI_FLASH_CFI_MFR_SST)write_sr (flash,0 ); +#ifdef CONFIG_SPI_FLASH_SST +if (info->flags &SST_ULBPR ) +sst26_unlock (flash); +#endif + flash->name = info->name; flash->memory_map = spi->memory_map;
@@ -1098,7 +1123,10 @@ int spi_flash_scan(struct spi_flash *flash) flash->erase_size =4096 << flash->shift; } else#endif - { +if (info->flags &SECT_4K_ONLY ) { + flash->erase_cmd =CMD_ERASE_4K ; + flash->erase_size =4096 << flash->shift; + }else { flash->erase_cmd =CMD_ERASE_64K ; flash->erase_size = flash->sector_size; }
drivers/mtd/spi/spi_flash_ids.c +5 -0
@@ -146,6 +146,11 @@ const struct spi_flash_info spi_flash_ids[] = { {"sst25wf040", INFO(0xbf2504, 0x0, 64 * 1024, 8, SECT_4K | SST_WR) }, {"sst25wf040b", INFO(0x621613, 0x0, 64 * 1024, 8, SECT_4K) }, {"sst25wf080", INFO(0xbf2505, 0x0, 64 * 1024, 16, SECT_4K | SST_WR) }, + {"sst26vf016b", INFO(0xbf2641, 0x0, 4 * 1024, 512, SECT_4K_ONLY | SST_ULBPR | RD_FULL) }, + {"sst26vf032b", INFO(0xbf2642, 0x0, 4 * 1024, 1024, SECT_4K_ONLY | SST_ULBPR | RD_FULL) }, + {"sst26vf064b", INFO(0xbf2643, 0x0, 4 * 1024, 2048, SECT_4K_ONLY | SST_ULBPR | RD_FULL) }, + {"sst26wf040b", INFO(0xbf2654, 0x0, 4 * 1024, 128, SECT_4K_ONLY | SST_ULBPR | RD_FULL) }, + {"sst26wf080b", INFO(0xbf2658, 0x0, 4 * 1024, 256, SECT_4K_ONLY | SST_ULBPR | RD_FULL) }, #endif #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */ {"w25p80", INFO(0xef2014, 0x0, 64 * 1024, 16, 0) },
Signature · 1 line
2.13.0
PATCH v2 8/8 sf: add driver for Atmel QSPI controller
In reply to Wenyou YangFrom: Cyrille Pitchen <[email protected]>
This patch adds support to the Atmel Quad SPI controller.
---
Changes in v2:
- Rebase on the latest u-boot/master(2710d54f5).
drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/atmel_qspi.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/spi/atmel_qspi.h | 169 ++++++++++++++++++++ 4 files changed, 581 insertions(+) create mode 100644 drivers/spi/atmel_qspi.c create mode 100644 drivers/spi/atmel_qspi.h
drivers/spi/Kconfig +7 -0
@@ -32,6 +32,13 @@ config ATH79_SPI uses driver model and requires a device tree binding to operate. please refer to doc/device-tree-bindings/spi/spi-ath79.txt. +config ATMEL_QSPI + bool "Atmel QSPI driver" + depends on ARCH_AT91 + help + Enable the Ateml Quad-SPI (QSPI) driver. This driver can only be + used to access SPI NOR flashes. + config ATMEL_SPI bool "Atmel SPI driver" depends on ARCH_AT91
drivers/spi/Makefile +1 -0
@@ -18,6 +18,7 @@ endif obj-$(CONFIG_ALTERA_SPI) += altera_spi.o obj-$(CONFIG_ATH79_SPI) += ath79_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_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o obj-$(CONFIG_CF_SPI) += cf_spi.o
drivers/spi/atmel_qspi.c new file +404 -0
404 lines not on this page · raw message
drivers/spi/atmel_qspi.h new file +169 -0
169 lines not on this page · raw message
Signature · 1 line
2.13.0