[U-Boot] [PATCH 3/4] sf: Add extended address access support
Jagannadha Sutradharudu Teki
jagannadha.sutradharudu-teki at xilinx.com
Sat Feb 23 12:39:00 CET 2013
This patch provides support to access an extended 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.
extended/bank address register contains an information to access the
4th byte addressing hence the flashes which has > 16MB can be accessible.
Signed-off-by: Jagannadha Sutradharudu Teki <jaganna at xilinx.com>
---
drivers/mtd/spi/spi_flash.c | 81 ++++++++++++++++++++++++++++++++++
drivers/mtd/spi/spi_flash_internal.h | 8 +++
2 files changed, 89 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index c168c1c..16e5f59 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -23,6 +23,30 @@ static void spi_flash_addr(u32 addr, u8 *cmd)
cmd[3] = addr >> 0;
}
+static int spi_flash_check_extaddr_access(struct spi_flash *flash, u32 *offset)
+{
+ int ret;
+
+ if (*offset >= 0x1000000) {
+ ret = spi_flash_extaddr_access(flash, STATUS_EXTADDR_ENABLE);
+ if (ret) {
+ debug("SF: fail to %s ext addr bit\n",
+ STATUS_EXTADDR_ENABLE ? "set" : "reset");
+ return ret;
+ }
+ *offset -= 0x1000000;
+ } else {
+ ret = spi_flash_extaddr_access(flash, STATUS_EXTADDR_DISABLE);
+ if (ret) {
+ debug("SF: fail to %s ext addr bit\n",
+ STATUS_EXTADDR_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,
@@ -73,6 +97,14 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
int ret;
u8 cmd[4];
+ if (flash->size > 0x1000000) {
+ ret = spi_flash_check_extaddr_access(flash, &offset);
+ if (ret) {
+ debug("SF: fail to acess ext_addr\n");
+ return ret;
+ }
+ }
+
page_size = flash->page_size;
page_addr = offset / page_size;
byte_addr = offset % page_size;
@@ -139,6 +171,15 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
size_t len, void *data)
{
u8 cmd[5];
+ int ret;
+
+ if (flash->size > 0x1000000) {
+ ret = spi_flash_check_extaddr_access(flash, &offset);
+ if (ret) {
+ debug("SF: fail to acess ext_addr\n");
+ return ret;
+ }
+ }
cmd[0] = CMD_READ_ARRAY_FAST;
spi_flash_addr(offset, cmd);
@@ -196,6 +237,14 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
int ret;
u8 cmd[4];
+ if (flash->size > 0x1000000) {
+ ret = spi_flash_check_extaddr_access(flash, &offset);
+ if (ret) {
+ debug("SF: fail to acess ext_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");
@@ -333,6 +382,38 @@ int spi_flash_cmd_extaddr_read(struct spi_flash *flash, void *data)
return spi_flash_read_common(flash, &cmd, 1, data, 1);
}
+int spi_flash_extaddr_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_extaddr_read(flash, (void *)&data);
+ if (ret < 0) {
+ debug("SF: fail to read ext addr register\n");
+ return ret;
+ }
+
+ if ((data != status) & !write_done) {
+ debug("SF: need to %s ext addr bit\n",
+ status ? "set" : "reset");
+
+ write_done = 1;
+ ret = spi_flash_cmd_extaddr_write(flash, status);
+ if (ret < 0) {
+ debug("SF: fail to write ext addr bit\n");
+ return ret;
+ }
+ } else {
+ debug("SF: ext addr bit is %s.\n",
+ status ? "set" : "reset");
+ return ret;
+ }
+ }
+
+ return -1;
+}
+
/*
* The following table holds all device probe functions
*
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h
index 65960ad..a6b04d7 100644
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/spi_flash_internal.h
@@ -34,6 +34,8 @@
/* Common status */
#define STATUS_WIP 0x01
+#define STATUS_EXTADDR_ENABLE 0x01
+#define STATUS_EXTADDR_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);
@@ -86,6 +88,12 @@ int spi_flash_cmd_extaddr_write(struct spi_flash *flash, u8 ear);
/* Read the extended address register */
int spi_flash_cmd_extaddr_read(struct spi_flash *flash, void *data);
+/*
+ * Extended address access
+ * access 4th byte address in 3-byte addessing mode for flashes
+ * which has an actual size of > 16MB.
+ */
+int spi_flash_extaddr_access(struct spi_flash *flash, u8 status);
/*
* Same as spi_flash_cmd_read() except it also claims/releases the SPI
--
1.7.4
More information about the U-Boot
mailing list