diff mbox

[U-Boot,3/8] sf: select the relevant SPI flash protocol for read and write commands

Message ID 2c794f0329b8109c94a754e064b2571a7d8b836c.1495204848.git.cyrille.pitchen@atmel.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Commit Message

Cyrille Pitchen May 19, 2017, 2:59 p.m. UTC
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.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
---
 drivers/mtd/spi/spi_flash.c | 24 ++++++++++++++++--------
 include/spi_flash.h         |  4 ++++
 2 files changed, 20 insertions(+), 8 deletions(-)

Comments

Wenyou Yang May 22, 2017, 1:18 a.m. UTC | #1
On 2017/5/19 22:59, Cyrille Pitchen wrote:
> 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.
>
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>

Acked-by Wenyou Yang <wenyou.yang@atmel.com>


Best Regards,
Wenyou Yang

> ---
>   drivers/mtd/spi/spi_flash.c | 24 ++++++++++++++++--------
>   include/spi_flash.h         |  4 ++++
>   2 files changed, 20 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
> index d0634e5b28c7..7e35fb9f4802 100644
> --- a/drivers/mtd/spi/spi_flash.c
> +++ b/drivers/mtd/spi/spi_flash.c
> @@ -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;
> @@ -1045,24 +1047,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",
> diff --git a/include/spi_flash.h b/include/spi_flash.h
> index be2fe3f84cb9..ac2b37f0202f 100644
> --- a/include/spi_flash.h
> +++ b/include/spi_flash.h
> @@ -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;
>
diff mbox

Patch

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index d0634e5b28c7..7e35fb9f4802 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -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;
@@ -1045,24 +1047,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",
diff --git a/include/spi_flash.h b/include/spi_flash.h
index be2fe3f84cb9..ac2b37f0202f 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -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;