From: Yang, Wenyou <Wenyou.Yang@Microchip.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 6/8] sf: add new option to support SPI flash above 16MiB
Date: Mon, 22 May 2017 09:20:14 +0800 [thread overview]
Message-ID: <c8ec0dfc-53fc-3d18-8a86-9fe498cd5c66@Microchip.com> (raw)
In-Reply-To: <bc2463b62baa14ab7c38f0a892a92b1acfdbb7b3.1495204848.git.cyrille.pitchen@atmel.com>
On 2017/5/19 22:59, Cyrille Pitchen wrote:
> 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>
Acked-by Wenyou Yang <wenyou.yang@atmel.com>
Best Regards,
Wenyou Yang
> ---
> drivers/mtd/spi/Kconfig | 15 ++++++-
> drivers/mtd/spi/sf_internal.h | 18 +++++++++
> drivers/mtd/spi/spi_flash.c | 92 ++++++++++++++++++++++++++++++++++++++++---
> 3 files changed, 118 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
> index 5ca0a712d84a..c11e83263b16 100644
> --- a/drivers/mtd/spi/Kconfig
> +++ b/drivers/mtd/spi/Kconfig
> @@ -34,14 +34,27 @@ 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
> +
> if SPI_FLASH
>
> config SPI_FLASH_ATMEL
> diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
> index 8b8c951bcc55..30994f9f460c 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 c5e00772f241..695c8555db3f 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)
> {
> @@ -966,6 +1027,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);
> @@ -1106,6 +1168,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);
> @@ -1131,13 +1213,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
>
next prev parent reply other threads:[~2017-05-22 1:20 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-19 14:59 [U-Boot] [PATCH 0/8] sf: improve support of (Q)SPI flash memories Cyrille Pitchen
2017-05-19 14:59 ` [U-Boot] [PATCH 1/8] spi: add support of SPI flash commands Cyrille Pitchen
2017-05-22 1:17 ` Yang, Wenyou
2017-05-19 14:59 ` [U-Boot] [PATCH 2/8] sf: describe all SPI flash commands with 'struct spi_flash_command' Cyrille Pitchen
2017-05-22 1:18 ` Yang, Wenyou
2017-05-19 14:59 ` [U-Boot] [PATCH 3/8] sf: select the relevant SPI flash protocol for read and write commands Cyrille Pitchen
2017-05-22 1:18 ` Yang, Wenyou
2017-05-19 14:59 ` [U-Boot] [PATCH 4/8] sf: differentiate Page Program 1-1-4 and 1-4-4 Cyrille Pitchen
2017-05-22 1:19 ` Yang, Wenyou
2017-05-19 14:59 ` [U-Boot] [PATCH 5/8] sf: add 'addr_len' member to 'struct spi_flash' Cyrille Pitchen
2017-05-22 1:19 ` Yang, Wenyou
2017-05-19 14:59 ` [U-Boot] [PATCH 6/8] sf: add new option to support SPI flash above 16MiB Cyrille Pitchen
2017-05-22 1:20 ` Yang, Wenyou [this message]
2017-05-19 14:59 ` [U-Boot] [PATCH 7/8] sf: add support to Microchip SST26 QSPI memories Cyrille Pitchen
2017-05-22 1:20 ` Yang, Wenyou
2017-05-19 14:59 ` [U-Boot] [PATCH 8/8] sf: add driver for Atmel QSPI controller Cyrille Pitchen
2017-05-22 1:21 ` Yang, Wenyou
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=c8ec0dfc-53fc-3d18-8a86-9fe498cd5c66@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox