diff options
author | Radu Bacrau <rbacrau@altera.com> | 2015-06-05 13:47:34 +0800 |
---|---|---|
committer | Tien Fong Chee <tfchee@pg-tfchee-lv.altera.com> | 2015-06-05 13:48:44 +0800 |
commit | 5a47f31c98e6c70185f3423bc82f3414cb25ca2c (patch) | |
tree | 9e0706401848cc6583fe7198c8ffee1eb3207924 | |
parent | da11abaa41a757ca164f147d0ef8ff3cfccf900c (diff) | |
download | u-boot-socfpga-5a47f31c98e6c70185f3423bc82f3414cb25ca2c.tar.gz |
FogBugz #297134: Supporting Spansion devices(S25FL127S/S25FL512S) with x4 moderel_socfpga_v2013.01.01_15.07.02_prrel_socfpga_v2013.01.01_15.07.01_prrel_socfpga_v2013.01.01_15.06.02_prACDS15.0.1_REL_GSRD_UPDATE1_PR
this patch enhanced the U-boot/SPL driver to support Spansion devices
(S25FL127S/S25FL512S) with x4 mode. This patch fixed the issue of
loading the next stage image from preloader also.
Signed-off-by: Radu Bacrau <rbacrau@altera.com>
Signed-off-by: Tien Fong Chee <tfchee@pg-tfchee-lv.altera.com>
-rw-r--r-- | drivers/mtd/spi/spansion.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index 9288672c84..33bf688096 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -31,6 +31,18 @@ #include "spi_flash_internal.h" +#define MAX_3BYTE_FLASH_SIZE 0x1000000 + +#define CMD_BANK_REGISTER_READ 0x16 +#define CMD_BANK_REGISTER_WRITE 0x17 +#define CMD_READ_CONFIG_REGISTER 0x35 +#define CMD_WRITE_REGISTERS 0x01 + +#define BANK_REGISTER_EXTADD_MASK 0x80 +#define CONF_REGISTER_QUAD_MASK 0x02 + +#define WRITE_REGISTERS_TIMEOUT CONFIG_SYS_HZ + struct spansion_spi_flash_params { u16 idcode1; u16 idcode2; @@ -105,12 +117,87 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { }, }; +static int spansion_spi_flash_enable_4_byte_address(struct spi_flash *flash) +{ + struct spi_slave *spi = flash->spi; + u8 cmd, data; + int err; + + cmd = CMD_BANK_REGISTER_READ; + err = spi_flash_cmd(spi, cmd, &data, 1); + if (err) { + debug("SF: Failed to read Spansion bank address register\n"); + return err; + } + + cmd = CMD_BANK_REGISTER_WRITE; + data |= BANK_REGISTER_EXTADD_MASK; + err = spi_flash_cmd_write(spi, &cmd, 1, &data, 1); + if (err) { + debug("SF: Failed to write Spansion bank address register\n"); + return err; + } + + return 0; +} + +static int spansion_spi_flash_enable_quad_mode(struct spi_flash *flash) +{ + struct spi_slave *spi = flash->spi; + u8 cmd, config, status; + u8 regs[2]; + int err; + + cmd = CMD_READ_CONFIG_REGISTER; + err = spi_flash_cmd_read(spi, &cmd, 1, &config, 1); + if (err) { + debug("SF: Failed to read config register\n"); + return err; + } + + if (config & CONF_REGISTER_QUAD_MASK) { + debug("SF: Device already configured for quad mode\n"); + return 0; + } + + cmd = CMD_READ_STATUS; + err = spi_flash_cmd_read(spi, &cmd, 1, &status, 1); + if (err) { + debug("SF: Failed to read status register\n"); + return err; + } + + err = spi_flash_cmd_write_enable(flash); + if (err) { + debug("SF: Failed to enable writing\n"); + return err; + } + + cmd = CMD_WRITE_REGISTERS; + regs[0] = status; + regs[1] = config | CONF_REGISTER_QUAD_MASK; + err = spi_flash_cmd_write(spi, &cmd, 1, regs, ARRAY_SIZE(regs)); + if (err) { + debug("SF: Failed to write registers\n"); + return err; + } + + err = spi_flash_cmd_wait_ready(flash, WRITE_REGISTERS_TIMEOUT); + if (err) { + debug("SF: Failed polling for write complete\n"); + return err; + } + + return 0; +} + struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) { const struct spansion_spi_flash_params *params; struct spi_flash *flash; unsigned int i; unsigned short jedec, ext_jedec; + int err; jedec = idcode[1] << 8 | idcode[2]; ext_jedec = idcode[3] << 8 | idcode[4]; @@ -134,6 +221,7 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) return NULL; } + memset(flash, 0, sizeof(*flash)); flash->spi = spi; flash->name = params->name; @@ -144,5 +232,23 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) flash->sector_size = 256 * params->pages_per_sector; flash->size = flash->sector_size * params->nr_sectors; + if (flash->size > MAX_3BYTE_FLASH_SIZE) { + err = spansion_spi_flash_enable_4_byte_address(flash); + if (err) { + debug("SF: Failed to enable 4 byte address mode\n"); + free(flash); + return NULL; + } + } + +#if (CONFIG_SPI_FLASH_QUAD == 1) + err = spansion_spi_flash_enable_quad_mode(flash); + if (err) { + debug("SF: Failed to enable quad mode\n"); + free(flash); + return NULL; + } +#endif + return flash; } |