@@ -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[];
@@ -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
@@ -1040,6 +1060,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;
@@ -1099,7 +1124,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;
}
@@ -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) },