summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRadu Bacrau <rbacrau@altera.com>2015-06-05 13:47:34 +0800
committerTien Fong Chee <tfchee@pg-tfchee-lv.altera.com>2015-06-05 13:48:44 +0800
commit5a47f31c98e6c70185f3423bc82f3414cb25ca2c (patch)
tree9e0706401848cc6583fe7198c8ffee1eb3207924
parentda11abaa41a757ca164f147d0ef8ff3cfccf900c (diff)
downloadu-boot-socfpga-5a47f31c98e6c70185f3423bc82f3414cb25ca2c.tar.gz
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.c106
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;
}