From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wenyou Yang Date: Tue, 25 Jul 2017 15:01:01 +0800 Subject: [U-Boot] [PATCH v3 7/8] sf: add support to Microchip SST26 QSPI memories In-Reply-To: <20170725070102.1344-1-wenyou.yang@microchip.com> References: <20170725070102.1344-1-wenyou.yang@microchip.com> Message-ID: <20170725070102.1344-8-wenyou.yang@microchip.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de From: Cyrille Pitchen 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. Signed-off-by: Cyrille Pitchen Signed-off-by: Wenyou Yang --- Changes in v3: None 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(-) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 30994f9f46..4354a2aa53 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -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[]; diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 89ceae2221..503059cacd 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -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; } diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c index edca94e30c..3d3132bc3b 100644 --- a/drivers/mtd/spi/spi_flash_ids.c +++ b/drivers/mtd/spi/spi_flash_ids.c @@ -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) }, -- 2.13.0