#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
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);
}
#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)
{
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;