All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wenyou Yang <wenyou.yang@microchip.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 6/8] sf: add new option to support SPI flash above 16MiB
Date: Tue, 25 Jul 2017 15:01:00 +0800	[thread overview]
Message-ID: <20170725070102.1344-7-wenyou.yang@microchip.com> (raw)
In-Reply-To: <20170725070102.1344-1-wenyou.yang@microchip.com>

From: Cyrille Pitchen <cyrille.pitchen@atmel.com>

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.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Signed-off-by: Wenyou Yang <wenyou.yang@microchip.com>
---

Changes in v3: None
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(-)

diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 5700859ff2..985aefd96c 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -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
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 8b8c951bcc..30994f9f46 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -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[];
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index d6942d57b2..89ceae2221 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -176,6 +176,67 @@ bar_end:
 }
 #endif
 
+#ifdef CONFIG_SPI_FLASH_4BAIS
+static u8 spi_flash_convert_opcode(u8 opcode, const u8 table[][2], size_t size)
+{
+	size_t i;
+
+	for (i = 0; i < size; i++)
+		if (table[i][0] == opcode)
+			return table[i][1];
+
+	/* No conversion found, keep input op code. */
+	return opcode;
+}
+
+static u8 spi_flash_convert_3to4_read(u8 opcode)
+{
+	static const u8 spi_flash_3to4_read[][2] = {
+		{CMD_READ_ARRAY_SLOW,		CMD_READ_ARRAY_SLOW_4B},
+		{CMD_READ_ARRAY_FAST,		CMD_READ_ARRAY_FAST_4B},
+		{CMD_READ_DUAL_OUTPUT_FAST,	CMD_READ_DUAL_OUTPUT_FAST_4B},
+		{CMD_READ_DUAL_IO_FAST,		CMD_READ_DUAL_IO_FAST_4B},
+		{CMD_READ_QUAD_OUTPUT_FAST,	CMD_READ_QUAD_OUTPUT_FAST_4B},
+		{CMD_READ_QUAD_IO_FAST,		CMD_READ_QUAD_IO_FAST_4B},
+	};
+
+	return spi_flash_convert_opcode(opcode, spi_flash_3to4_read,
+					ARRAY_SIZE(spi_flash_3to4_read));
+}
+
+static u8 spi_flash_convert_3to4_write(u8 opcode)
+{
+	static const u8 spi_flash_3to4_write[][2] = {
+		{CMD_PAGE_PROGRAM,		CMD_PAGE_PROGRAM_4B},
+		{CMD_PAGE_PROGRAM_1_1_4,	CMD_PAGE_PROGRAM_1_1_4_4B},
+		{CMD_PAGE_PROGRAM_1_4_4,	CMD_PAGE_PROGRAM_1_4_4_4B},
+	};
+
+	return spi_flash_convert_opcode(opcode, spi_flash_3to4_write,
+					ARRAY_SIZE(spi_flash_3to4_write));
+}
+
+static u8 spi_flash_convert_3to4_erase(u8 opcode)
+{
+	static const u8 spi_flash_3to4_erase[][2] = {
+		{CMD_ERASE_4K,	CMD_ERASE_4K_4B},
+		{CMD_ERASE_64K,	CMD_ERASE_64K_4B},
+	};
+
+	return spi_flash_convert_opcode(opcode, spi_flash_3to4_erase,
+					ARRAY_SIZE(spi_flash_3to4_erase));
+}
+
+static void spi_flash_set_4byte_addr_opcodes(struct spi_flash *flash,
+					     const struct spi_flash_info *info)
+{
+	flash->read_cmd = spi_flash_convert_3to4_read(flash->read_cmd);
+	flash->write_cmd = spi_flash_convert_3to4_write(flash->write_cmd);
+	flash->erase_cmd = spi_flash_convert_3to4_erase(flash->erase_cmd);
+	flash->addr_len = SPI_FLASH_4B_ADDR_LEN;
+}
+#endif
+
 #ifdef CONFIG_SF_DUAL_FLASH
 static void spi_flash_dual(struct spi_flash *flash, u32 *addr)
 {
@@ -965,6 +1026,7 @@ int spi_flash_scan(struct spi_flash *flash)
 {
 	struct spi_slave *spi = flash->spi;
 	const struct spi_flash_info *info = NULL;
+	bool above_16MB;
 	int ret;
 
 	info = spi_flash_read_id(flash);
@@ -1105,6 +1167,26 @@ int spi_flash_scan(struct spi_flash *flash)
 	/* Set the address length */
 	flash->addr_len = SPI_FLASH_3B_ADDR_LEN;
 
+	above_16MB = ((flash->dual_flash == SF_SINGLE_FLASH) &&
+		      (flash->size > SPI_FLASH_16MB_BOUN)) ||
+		     ((flash->dual_flash > SF_SINGLE_FLASH) &&
+		      (flash->size > SPI_FLASH_16MB_BOUN << 1));
+
+	/*
+	 * replace the selected 3-byte address op codes with the associated
+	 * 4-byte address op codes, if needed (flash->size > 16 MiB)
+	 */
+#ifdef CONFIG_SPI_FLASH_4BAIS
+	if (above_16MB) {
+		if (info->flags & NO_4BAIS) {
+			puts("SF: Warning - Only lower 16MiB accessible,");
+			puts(" 4-byte address instruction set not supported\n");
+		} else {
+			spi_flash_set_4byte_addr_opcodes(flash, info);
+		}
+	}
+#endif
+
 	/* Configure the BAR - discover bank cmds and read current bank */
 #ifdef CONFIG_SPI_FLASH_BAR
 	ret = read_bar(flash, info);
@@ -1130,13 +1212,11 @@ int spi_flash_scan(struct spi_flash *flash)
 	puts("\n");
 #endif
 
-#ifndef CONFIG_SPI_FLASH_BAR
-	if (((flash->dual_flash == SF_SINGLE_FLASH) &&
-	     (flash->size > SPI_FLASH_16MB_BOUN)) ||
-	     ((flash->dual_flash > SF_SINGLE_FLASH) &&
-	     (flash->size > SPI_FLASH_16MB_BOUN << 1))) {
+#if !defined(CONFIG_SPI_FLASH_BAR) && !defined(CONFIG_SPI_FLASH_4BAIS)
+	if (above_16MB) {
 		puts("SF: Warning - Only lower 16MiB accessible,");
-		puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
+		puts(" Full access #define CONFIG_SPI_FLASH_BAR");
+		puts(" or CONFIG_SPI_FLASH_4BAIS\n");
 	}
 #endif
 
-- 
2.13.0

  parent reply	other threads:[~2017-07-25  7:01 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-25  7:00 [U-Boot] [PATCH v3 0/8] sf: improve support of (Q)SPI flash memories Wenyou Yang
2017-07-25  7:00 ` [U-Boot] [PATCH v3 1/8] spi: add support of SPI flash commands Wenyou Yang
2017-08-30 13:50   ` Jagan Teki
2017-09-01  0:10     ` Wenyou.Yang at microchip.com
2017-07-25  7:00 ` [U-Boot] [PATCH v3 2/8] sf: describe all SPI flash commands with 'struct spi_flash_command' Wenyou Yang
2017-08-30 14:03   ` Jagan Teki
2017-07-25  7:00 ` [U-Boot] [PATCH v3 3/8] sf: select the relevant SPI flash protocol for read and write commands Wenyou Yang
2017-07-25  7:00 ` [U-Boot] [PATCH v3 4/8] sf: differentiate Page Program 1-1-4 and 1-4-4 Wenyou Yang
2017-07-25  7:00 ` [U-Boot] [PATCH v3 5/8] sf: add 'addr_len' member to 'struct spi_flash' Wenyou Yang
2017-07-25  7:01 ` Wenyou Yang [this message]
2017-07-25  7:01 ` [U-Boot] [PATCH v3 7/8] sf: add support to Microchip SST26 QSPI memories Wenyou Yang
2017-07-25  7:01 ` [U-Boot] [PATCH v3 8/8] sf: add driver for Atmel QSPI controller Wenyou Yang
2017-08-30 13:58   ` Jagan Teki
2017-07-31  7:29 ` [U-Boot] [PATCH v3 0/8] sf: improve support of (Q)SPI flash memories Yang, Wenyou
2017-08-11  1:02 ` Yang, Wenyou
2017-08-11  5:14   ` Jagan Teki
2017-08-25  1:17 ` Yang, Wenyou
2017-08-25 16:07   ` Jagan Teki
2017-08-25 16:13     ` Marek Vasut
2017-08-25 16:28       ` Jagan Teki
2017-08-25 16:45         ` Marek Vasut
2017-08-25 23:05           ` Bin Meng
2017-08-26  6:14             ` Jagan Teki
2017-08-26  8:36               ` Marek Vasut
2017-08-26 19:12                 ` Tom Rini
2017-08-26  6:34 ` Jagan Teki
2017-08-30  1:58   ` Yang, Wenyou
2017-08-30  6:33     ` Jagan Teki
2017-08-30  3:25   ` Yang, Wenyou
2017-08-30  3:43     ` Bin Meng
2017-08-30  5:27       ` Yang, Wenyou
2017-08-30  5:41         ` Bin Meng
2017-08-30  5:51           ` Yang, Wenyou
2017-08-30  6:30           ` Jagan Teki
2017-08-30  7:47             ` Bin Meng
2017-08-30 13:25               ` Jagan Teki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170725070102.1344-7-wenyou.yang@microchip.com \
    --to=wenyou.yang@microchip.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.