]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
sf: Add bank address access support
authorJagannadha Sutradharudu Teki <jaganna@xilinx.com>
Sat, 5 Jan 2013 13:42:12 +0000 (19:12 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Tue, 22 Jan 2013 13:16:35 +0000 (14:16 +0100)
This patch provides support to access bank addressing
in 3-byte address mode.

The current implementation in spi_flash supports 3-byte address mode
due to this up to 16MB amount of flash is able to access for those
flashes which has an actual size of > 16MB.

bank address register contains an information to access the
4th byte address so-that the flashes which has > 16MB can be accessible.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
drivers/mtd/spi/spi_flash.c
drivers/mtd/spi/spi_flash_internal.h

index 90c51c7110d95b5c5788e267a4e165ac68e3dc1e..7bc4322d83a9d0d9f97d3d7156ab46f7258b743d 100644 (file)
@@ -12,6 +12,7 @@
 #include <spi.h>
 #include <spi_flash.h>
 #include <watchdog.h>
+#include <asm/sizes.h>
 
 #include "spi_flash_internal.h"
 
@@ -31,6 +32,30 @@ static void spi_flash_addr(struct spi_flash *flash,
        }
 }
 
+static int spi_flash_check_bankaddr_access(struct spi_flash *flash, u32 *offset)
+{
+       int ret;
+
+       if (*offset >= SZ_16M) {
+               ret = spi_flash_bankaddr_access(flash, STATUS_BANKADDR_ENABLE);
+               if (ret) {
+                       debug("SF: fail to %s bank addr bit\n",
+                               STATUS_BANKADDR_ENABLE ? "set" : "reset");
+                       return ret;
+               }
+               *offset -= SZ_16M;
+       } else {
+               ret = spi_flash_bankaddr_access(flash, STATUS_BANKADDR_DISABLE);
+               if (ret) {
+                       debug("SF: fail to %s bank addr bit\n",
+                               STATUS_BANKADDR_DISABLE ? "set" : "reset");
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
 static int spi_flash_read_write(struct spi_slave *spi,
                                const u8 *cmd, size_t cmd_len,
                                const u8 *data_out, u8 *data_in,
@@ -81,6 +106,14 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
        int ret;
        u8 cmd[flash->addr_width+1];
 
+       if ((flash->size > SZ_16M) && (flash->addr_width == 3)) {
+               ret = spi_flash_check_bankaddr_access(flash, &offset);
+               if (ret) {
+                       debug("SF: fail to acess bank_addr\n");
+                       return ret;
+               }
+       }
+
        page_size = flash->page_size;
        page_addr = offset / page_size;
        byte_addr = offset % page_size;
@@ -149,6 +182,15 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
        unsigned long page_size;
        unsigned long byte_addr;
        u8 cmd[flash->addr_width+2];
+       int ret;
+
+       if ((flash->size > SZ_16M) && (flash->addr_width == 3)) {
+               ret = spi_flash_check_bankaddr_access(flash, &offset);
+               if (ret) {
+                       debug("SF: fail to acess bank_addr\n");
+                       return ret;
+               }
+       }
 
        page_size = flash->page_size;
        page_addr = offset / page_size;
@@ -211,6 +253,14 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
        unsigned long page_addr;
        u8 cmd[flash->addr_width+1];
 
+       if ((flash->size > SZ_16M) && (flash->addr_width == 3)) {
+               ret = spi_flash_check_bankaddr_access(flash, &offset);
+               if (ret) {
+                       debug("SF: fail to acess bank_addr\n");
+                       return ret;
+               }
+       }
+
        erase_size = flash->sector_size;
        if (offset % erase_size || len % erase_size) {
                debug("SF: Erase offset/length not multiple of erase size\n");
@@ -320,6 +370,38 @@ int spi_flash_cmd_bankaddr_read(struct spi_flash *flash, void *data)
        return spi_flash_read_common(flash, &cmd, 1, data, 1);
 }
 
+int spi_flash_bankaddr_access(struct spi_flash *flash, u8 status)
+{
+       int ret, pass;
+       u8 data = 0, write_done = 0;
+
+       for (pass = 0; pass < 2; pass++) {
+               ret = spi_flash_cmd_bankaddr_read(flash, (void *)&data);
+               if (ret < 0) {
+                       debug("SF: fail to read bank addr register\n");
+                       return ret;
+               }
+
+               if ((data != status) & !write_done) {
+                       debug("SF: need to %s bank addr bit\n",
+                                               status ? "set" : "reset");
+
+                       write_done = 1;
+                       ret = spi_flash_cmd_bankaddr_write(flash, status);
+                       if (ret < 0) {
+                               debug("SF: fail to write bank addr bit\n");
+                               return ret;
+                       }
+               } else {
+                       debug("SF: bank addr bit is %s.\n",
+                                               status ? "set" : "reset");
+                       return ret;
+               }
+       }
+
+       return -1;
+}
+
 /*
  * The following table holds all device probe functions
  *
index bb22f5cd8d647bc2fda6d6aaa47ee072e0163877..dc411e551970b36f9579ebd42014fc4abfe42028 100644 (file)
@@ -34,6 +34,8 @@
 
 /* Common status */
 #define STATUS_WIP                     0x01
+#define STATUS_BANKADDR_ENABLE         0x01
+#define STATUS_BANKADDR_DISABLE        0x00
 
 /* Send a single-byte command to the device and read the response */
 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
@@ -87,6 +89,13 @@ int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 ear);
 /* Read the bank address register */
 int spi_flash_cmd_bankaddr_read(struct spi_flash *flash, void *data);
 
+/*
+ * Bank address access
+ * access 4th byte address in 3-byte addessing mode for flashes
+ * which has an actual size of > 16MB.
+ */
+int spi_flash_bankaddr_access(struct spi_flash *flash, u8 status);
+
 /*
  * Same as spi_flash_cmd_read() except it also claims/releases the SPI
  * bus. Used as common part of the ->read() operation.