Blackfin: add support for SST SPI flashes
authorMike Frysinger <vapier@gentoo.org>
Sun, 12 Oct 2008 02:51:05 +0000 (22:51 -0400)
committerMike Frysinger <vapier@gentoo.org>
Wed, 25 Mar 2009 00:36:30 +0000 (20:36 -0400)
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
board/bf537-stamp/spi_flash.c

index 797daf2..a336894 100644 (file)
@@ -59,6 +59,15 @@ static struct flash_info flash_st_serial_flash[] = {
        { NULL, 0, 0, 0 }
 };
 
+/* SPI Speeds: 20 MHz / 40 MHz */
+static struct flash_info flash_sst_serial_flash[] = {
+       { "SST25WF512", 0x2501, 4 * 1024, 128 },
+       { "SST25WF010", 0x2502, 4 * 1024, 256 },
+       { "SST25WF020", 0x2503, 4 * 1024, 512 },
+       { "SST25WF040", 0x2504, 4 * 1024, 1024 },
+       { NULL, 0, 0, 0 }
+};
+
 /* SPI Speeds: 66 MHz / 33 MHz */
 static struct flash_info flash_atmel_dataflash[] = {
        { "AT45DB011x", 0x0c, 264, 512 },
@@ -98,6 +107,13 @@ static struct flash_ops flash_st_ops = {
        .status = 0x05,
 };
 
+static struct flash_ops flash_sst_ops = {
+       .read = OP_READ,
+       .write = 0x02,
+       .erase = 0x20,
+       .status = 0x05,
+};
+
 static struct flash_ops flash_atmel_ops = {
        .read = OP_READ,
        .write = 0x82,
@@ -131,6 +147,7 @@ static struct {
 enum {
        JED_MANU_SPANSION = 0x01,
        JED_MANU_ST       = 0x20,
+       JED_MANU_SST      = 0xBF,
        JED_MANU_ATMEL    = 0x1F,
        JED_MANU_WINBOND  = 0xEF,
 };
@@ -149,6 +166,12 @@ static struct manufacturer_info flash_manufacturers[] = {
                .ops = &flash_st_ops,
        },
        {
+               .name = "SST",
+               .id = JED_MANU_SST,
+               .flashes = flash_sst_serial_flash,
+               .ops = &flash_sst_ops,
+       },
+       {
                .name = "Atmel",
                .id = JED_MANU_ATMEL,
                .flashes = flash_atmel_dataflash,
@@ -276,6 +299,7 @@ static int wait_for_ready_status(void)
                switch (flash.manufacturer_id) {
                case JED_MANU_SPANSION:
                case JED_MANU_ST:
+               case JED_MANU_SST:
                case JED_MANU_WINBOND:
                        if (!(read_status_register() & 0x01))
                                return 0;
@@ -297,6 +321,50 @@ static int wait_for_ready_status(void)
        return -1;
 }
 
+static int enable_writing(void)
+{
+       ulong start;
+
+       if (flash.manufacturer_id == JED_MANU_ATMEL)
+               return 0;
+
+       /* A write enable instruction must previously have been executed */
+       SPI_ON();
+       spi_write_read_byte(0x06);
+       SPI_OFF();
+
+       /* The status register will be polled to check the write enable latch "WREN" */
+       start = get_timer(0);
+       while (get_timer(0) - start < TIMEOUT) {
+               if (read_status_register() & 0x02)
+                       return 0;
+
+               if (ctrlc()) {
+                       puts("\nAbort\n");
+                       return -1;
+               }
+       }
+
+       puts("Timeout\n");
+       return -1;
+}
+
+static void write_status_register(uint8_t val)
+{
+       if (flash.manufacturer_id != JED_MANU_SST)
+               hang();
+
+       if (enable_writing())
+               return;
+
+       /* send instruction to write status register */
+       SPI_ON();
+       spi_write_read_byte(0x01);
+       /* and clear it! */
+       spi_write_read_byte(val);
+       SPI_OFF();
+}
+
 /* Request and read the manufacturer and device id of parts which
  * are compatible with the JEDEC standard (JEP106) and use that to
  * setup other operating conditions.
@@ -351,6 +419,7 @@ static int spi_detect_part(void)
        switch (flash.manufacturer_id) {
        case JED_MANU_SPANSION:
        case JED_MANU_ST:
+       case JED_MANU_SST:
        case JED_MANU_WINBOND:
                for (i = 0; flash.manufacturer->flashes[i].name; ++i) {
                        if (dev_id == flash.manufacturer->flashes[i].id)
@@ -362,7 +431,11 @@ static int spi_detect_part(void)
                flash.flash = &flash.manufacturer->flashes[i];
                flash.sector_size = flash.flash->sector_size;
                flash.num_sectors = flash.flash->num_sectors;
-               flash.write_length = 256;
+
+               if (flash.manufacturer_id == JED_MANU_SST)
+                       flash.write_length = 1; /* pwnt :( */
+               else
+                       flash.write_length = 256;
                break;
 
        case JED_MANU_ATMEL: {
@@ -388,6 +461,10 @@ static int spi_detect_part(void)
        }
        }
 
+       /* the SST parts power up with software protection enabled by default */
+       if (flash.manufacturer_id == JED_MANU_SST)
+               write_status_register(0);
+
        called_init = 1;
        return 0;
 
@@ -572,34 +649,6 @@ static int read_flash(unsigned long address, long count, uchar *buffer)
        return 0;
 }
 
-static int enable_writing(void)
-{
-       ulong start;
-
-       if (flash.manufacturer_id == JED_MANU_ATMEL)
-               return 0;
-
-       /* A write enable instruction must previously have been executed */
-       SPI_ON();
-       spi_write_read_byte(0x06);
-       SPI_OFF();
-
-       /* The status register will be polled to check the write enable latch "WREN" */
-       start = get_timer(0);
-       while (get_timer(0) - start < TIMEOUT) {
-               if (read_status_register() & 0x02)
-                       return 0;
-
-               if (ctrlc()) {
-                       puts("\nAbort\n");
-                       return -1;
-               }
-       }
-
-       puts("Timeout\n");
-       return -1;
-}
-
 static long address_to_sector(unsigned long address)
 {
        if (address > (flash.num_sectors * flash.sector_size) - 1)