From 3b297cacc02b6dd517b5650ed5120ae9d37a8b0e Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Fri, 14 Aug 2015 14:41:14 +0530 Subject: [PATCH] sf: Turn SPI flash chip into 3-Byte address mode For more than 16MiB SPI flash chips, there are 3-Byte and 4-Byte address mode, and only the 3-Byte address mode is supported in U-Boot so far. So, reset the SPI flash to 3-Byte address mode in probe to ensure the SPI flash work correctly, because it may has been set to 4-Byte address mode after warm boot. Signed-off-by: Hou Zhiqiang Signed-off-by: Michal Simek --- drivers/mtd/spi/sf_internal.h | 6 ++++++ drivers/mtd/spi/sf_ops.c | 40 +++++++++++++++++++++++++++++++++++ drivers/mtd/spi/sf_probe.c | 11 ++++++++++ 3 files changed, 57 insertions(+) diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index dc192e20a0a..44f0e07db02 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -76,6 +76,9 @@ enum { #define CMD_WRITE_ENABLE 0x06 #define CMD_READ_CONFIG 0x35 #define CMD_FLAG_STATUS 0x70 +/* Used for Micron, Macronix and Winbond flashes */ +#define CMD_ENTER_4B_ADDR 0xB7 +#define CMD_EXIT_4B_ADDR 0xE9 /* Read commands */ #define CMD_READ_ARRAY_SLOW 0x03 @@ -221,6 +224,9 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, size_t len, void *data); +int spi_flash_cmd_4B_addr_switch(struct spi_flash *flash, + int enable, u8 idcode0); + #ifdef CONFIG_SPI_FLASH_MTD int spi_flash_mtd_register(struct spi_flash *flash); void spi_flash_mtd_unregister(void); diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index d1bb41bcfe5..87818196d2e 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -126,6 +126,46 @@ int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc) } #endif +int spi_flash_cmd_4B_addr_switch(struct spi_flash *flash, + int enable, u8 idcode0) +{ + int ret; + u8 cmd, bar; + bool need_wren = false; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: unable to claim SPI bus\n"); + return ret; + } + + switch (idcode0) { + case SPI_FLASH_CFI_MFR_STMICRO: + /* Some Micron need WREN command; all will accept it */ + need_wren = true; + case SPI_FLASH_CFI_MFR_MACRONIX: + case SPI_FLASH_CFI_MFR_WINBOND: + if (need_wren) + spi_flash_cmd_write_enable(flash); + + cmd = enable ? CMD_ENTER_4B_ADDR : CMD_EXIT_4B_ADDR; + ret = spi_flash_cmd(flash->spi, cmd, NULL, 0); + if (need_wren) + spi_flash_cmd_write_disable(flash); + + break; + default: + /* Spansion style */ + bar = enable << 7; + cmd = CMD_BANKADDR_BRWR; + ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &bar, 1); + } + + spi_release_bus(flash->spi); + + return ret; +} + #ifdef CONFIG_SPI_FLASH_BAR static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) { diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 5377c2f623d..bbb51ef9bd5 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -207,6 +207,17 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, flash->page_size <<= flash->shift; flash->sector_size = params->sector_size << flash->shift; flash->size = flash->sector_size * params->nr_sectors; + + /* + * So far, the 4-byte address mode haven't been supported in U-Boot, + * and make sure the chip (> 16MiB) in default 3-byte address mode, + * in case of warm bootup, the chip was set to 4-byte mode in kernel. + */ + if (flash->size > SPI_FLASH_16MB_BOUN) { + if (spi_flash_cmd_4B_addr_switch(flash, false, idcode[0]) < 0) + debug("SF: enter 3B address mode failed\n"); + } + #ifdef CONFIG_SF_DUAL_FLASH if (flash->dual_flash & SF_DUAL_STACKED_FLASH) flash->size <<= 1; -- 2.47.3