]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
sf: Changes to support generic qspi
authorSiva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
Sat, 28 Feb 2015 07:15:03 +0000 (12:45 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Tue, 3 Mar 2015 11:28:30 +0000 (12:28 +0100)
Changes to support generic qspi controller
in handling two separate requests and responses
from two spi flash devices in dual parallel
configuration.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/mtd/spi/sf.c
drivers/mtd/spi/sf_ops.c
drivers/mtd/spi/sf_probe.c
include/spi.h

index 664e86082b19c95e08a68f1443f1efd18f89d5ca..d2f84619de76e1a6de10169d1d55cb27ee0dc2e7 100644 (file)
@@ -15,28 +15,38 @@ static int spi_flash_read_write(struct spi_slave *spi,
                                const u8 *data_out, u8 *data_in,
                                size_t data_len)
 {
-       unsigned long flags = SPI_XFER_BEGIN;
+       unsigned long flags = 0;
        int ret;
 
 #ifdef CONFIG_SF_DUAL_FLASH
        if (spi->flags & SPI_XFER_U_PAGE)
                flags |= SPI_XFER_U_PAGE;
+#ifdef CONFIG_SPI_GENERIC
+       if (spi->flags & SPI_XFER_LOWER)
+               flags |= SPI_XFER_LOWER;
+       if (spi->flags & SPI_XFER_UPPER)
+               flags |= SPI_XFER_UPPER;
+       if (spi->flags & SPI_XFER_STRIPE)
+               flags |= SPI_XFER_STRIPE;
+#endif
 #endif
        if (data_len == 0)
                flags |= SPI_XFER_END;
 
-       ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
+       ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags | SPI_XFER_BEGIN);
        if (ret) {
                debug("SF: Failed to send command (%zu bytes): %d\n",
                      cmd_len, ret);
        } else if (data_len != 0) {
                ret = spi_xfer(spi, data_len * 8, data_out, data_in,
-                                       SPI_XFER_END);
+                                       flags | SPI_XFER_END);
                if (ret)
                        debug("SF: Failed to transfer %zu bytes of data: %d\n",
                              data_len, ret);
        }
-
+#ifdef CONFIG_SPI_GENERIC
+       spi->flags &= ~SPI_XFER_MASK;
+#endif
        return ret;
 }
 
index fc0ba2ab446081a9c57bd0c720dfab1c18aedf20..1ce4ab7b7fd19e018d2811f48f16ce9d1e9550aa 100644 (file)
@@ -74,13 +74,34 @@ int spi_flash_cmd_read_config(struct spi_flash *flash, u8 *rc)
 int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc)
 {
        u8 data[2];
+#ifdef CONFIG_SPI_GENERIC
+       u8 dataup[2];
+#endif
        u8 cmd;
        int ret;
 
+#ifdef CONFIG_SPI_GENERIC
+       if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH)
+               flash->spi->flags |= SPI_XFER_LOWER;
+#endif
        ret = spi_flash_cmd_read_status(flash, &data[0]);
        if (ret < 0)
                return ret;
 
+#ifdef CONFIG_SPI_GENERIC
+       if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) {
+               flash->spi->flags |= SPI_XFER_UPPER;
+               ret = spi_flash_cmd_read_status(flash, &dataup[0]);
+               if (ret < 0)
+                       return ret;
+       }
+#endif
+
+#ifdef CONFIG_SPI_GENERIC
+       if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH)
+               flash->spi->flags |= SPI_XFER_LOWER;
+#endif
+
        cmd = CMD_WRITE_STATUS;
        data[1] = wc;
        ret = spi_flash_write_common(flash, &cmd, 1, &data, 2);
@@ -89,6 +110,18 @@ int spi_flash_cmd_write_config(struct spi_flash *flash, u8 wc)
                return ret;
        }
 
+#ifdef CONFIG_SPI_GENERIC
+       if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) {
+               flash->spi->flags |= SPI_XFER_UPPER;
+               dataup[1] = wc;
+               ret = spi_flash_write_common(flash, &cmd, 1, &dataup, 2);
+               if (ret) {
+                       debug("SF: fail to write config register\n");
+                       return ret;
+               }
+       }
+#endif
+
        return 0;
 }
 #endif
@@ -166,14 +199,18 @@ static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr)
 }
 #endif
 
-static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
+static int spi_flash_poll_status(struct spi_flash *flash, unsigned long timeout,
                                 u8 cmd, u8 poll_bit)
 {
+       struct spi_slave *spi = flash->spi;
        unsigned long timebase;
-       unsigned long flags = SPI_XFER_BEGIN;
+       unsigned long flags = 0;
        int ret;
        u8 status;
        u8 check_status = 0x0;
+#ifdef CONFIG_SPI_GENERIC
+       u8 status_up;
+#endif
 
        if (cmd == CMD_FLAG_STATUS)
                check_status = poll_bit;
@@ -182,7 +219,7 @@ static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
        if (spi->flags & SPI_XFER_U_PAGE)
                flags |= SPI_XFER_U_PAGE;
 #endif
-       ret = spi_xfer(spi, 8, &cmd, NULL, flags);
+       ret = spi_xfer(spi, 8, &cmd, NULL, flags | SPI_XFER_BEGIN);
        if (ret) {
                debug("SF: fail to read %s status register\n",
                      cmd == CMD_READ_STATUS ? "read" : "flag");
@@ -193,20 +230,50 @@ static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
        do {
                WATCHDOG_RESET();
 
-               ret = spi_xfer(spi, 8, NULL, &status, 0);
-               if (ret)
-                       return -1;
-
-               if ((status & poll_bit) == check_status)
-                       break;
-
+#ifdef CONFIG_SPI_GENERIC
+               if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) {
+                       ret = spi_xfer(spi, 8, NULL, &status,
+                                      flags | SPI_XFER_LOWER);
+                       if (ret)
+                               return -1;
+                       ret = spi_xfer(spi, 8, NULL, &status_up,
+                                      flags | SPI_XFER_UPPER);
+                       if (ret)
+                               return -1;
+                       debug("Poll Status:0x%x, Status_up:0x%x\n", status,
+                             status_up);
+
+                       if (((status & poll_bit) == check_status) &&
+                           ((status_up & poll_bit) == check_status))
+                               break;
+               } else {
+#endif
+                       ret = spi_xfer(spi, 8, NULL, &status, flags);
+                       if (ret)
+                               return -1;
+
+                       debug("Poll Status:0x%x\n", status);
+                       if ((status & poll_bit) == check_status)
+                               break;
+#ifdef CONFIG_SPI_GENERIC
+               }
+#endif
        } while (get_timer(timebase) < timeout);
 
-       spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+       spi_xfer(spi, 0, NULL, NULL, flags | SPI_XFER_END);
 
+#ifdef CONFIG_SPI_GENERIC
+       if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) {
+               if (((status & poll_bit) == check_status) &&
+                   ((status_up & poll_bit) == check_status))
+                       return 0;
+       } else {
+#endif
        if ((status & poll_bit) == check_status)
                return 0;
-
+#ifdef CONFIG_SPI_GENERIC
+       }
+#endif
        /* Timed out */
        debug("SF: time out!\n");
        return -1;
@@ -214,19 +281,18 @@ static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
 
 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
 {
-       struct spi_slave *spi = flash->spi;
        int ret;
        u8 poll_bit = STATUS_WIP;
        u8 cmd = CMD_READ_STATUS;
 
-       ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
+       ret = spi_flash_poll_status(flash, timeout, cmd, poll_bit);
        if (ret < 0)
                return ret;
 
        if (flash->poll_cmd == CMD_FLAG_STATUS) {
                poll_bit = STATUS_PEC;
                cmd = CMD_FLAG_STATUS;
-               ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
+               ret = spi_flash_poll_status(flash, timeout, cmd, poll_bit);
                if (ret < 0)
                        return ret;
        }
@@ -360,6 +426,10 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
                debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
                      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
 
+#ifdef CONFIG_SPI_GENERIC
+               if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH)
+                       flash->spi->flags |= SPI_XFER_STRIPE;
+#endif
                ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
                                        buf + actual, chunk_len);
                if (ret < 0) {
@@ -453,6 +523,11 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
 
                spi_flash_addr(read_addr, cmd);
 
+#ifdef CONFIG_SPI_GENERIC
+               if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH)
+                       flash->spi->flags |= SPI_XFER_STRIPE;
+#endif
+
                ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
                if (ret < 0) {
                        debug("SF: read failed\n");
index 93ee92498a4fba39adcbc17531f98d084b8b4bb9..d8fce40709888d623855e0a96253f9b7ce93abd9 100644 (file)
@@ -35,13 +35,31 @@ static u8 spi_read_cmds_array[] = {
 static int spi_flash_set_qeb_mxic(struct spi_flash *flash)
 {
        u8 qeb_status;
+#ifdef CONFIG_SPI_GENERIC
+       u8 qeb_status_up;
+#endif
        int ret;
 
+#ifdef CONFIG_SPI_GENERIC
+       if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH)
+               flash->spi->flags |= SPI_XFER_LOWER;
+#endif
+
        ret = spi_flash_cmd_read_status(flash, &qeb_status);
        if (ret < 0)
                return ret;
 
-       if (qeb_status & STATUS_QEB_MXIC) {
+#ifdef CONFIG_SPI_GENERIC
+       if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) {
+               flash->spi->flags |= SPI_XFER_UPPER;
+               spi_flash_cmd_read_status(flash, &qeb_status_up);
+       }
+#endif
+       if ((qeb_status & STATUS_QEB_MXIC)
+#ifdef CONFIG_SPI_GENERIC
+            && (qeb_status_up & STATUS_QEB_MXIC)
+#endif
+       ) {
                debug("SF: mxic: QEB is already set\n");
        } else {
                ret = spi_flash_cmd_write_status(flash, STATUS_QEB_MXIC);
@@ -57,13 +75,31 @@ static int spi_flash_set_qeb_mxic(struct spi_flash *flash)
 static int spi_flash_set_qeb_winspan(struct spi_flash *flash)
 {
        u8 qeb_status;
+#ifdef CONFIG_SPI_GENERIC
+       u8 qeb_status_up;
+#endif
        int ret;
 
+#ifdef CONFIG_SPI_GENERIC
+       if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH)
+               flash->spi->flags |= SPI_XFER_LOWER;
+#endif
+
        ret = spi_flash_cmd_read_config(flash, &qeb_status);
        if (ret < 0)
                return ret;
 
-       if (qeb_status & STATUS_QEB_WINSPAN) {
+#ifdef CONFIG_SPI_GENERIC
+       if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) {
+               flash->spi->flags |= SPI_XFER_UPPER;
+               ret = spi_flash_cmd_read_config(flash, &qeb_status_up);
+       }
+#endif
+       if ((qeb_status & STATUS_QEB_WINSPAN)
+#ifdef CONFIG_SPI_GENERIC
+           && (qeb_status_up & STATUS_QEB_WINSPAN)
+#endif
+       ) {
                debug("SF: winspan: QEB is already set\n");
        } else {
                ret = spi_flash_cmd_write_config(flash, STATUS_QEB_WINSPAN);
@@ -258,11 +294,15 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
                flash->bank_write_cmd = (idcode[0] == 0x01) ?
                                        CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR;
 
-               ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
-                                           &curr_bank, 1);
-               if (ret) {
-                       debug("SF: fail to read bank addr register\n");
-                       return ret;
+               if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) {
+                       spi->flags |= SPI_XFER_LOWER;
+                       ret = spi_flash_read_common(flash,
+                                                    &flash->bank_read_cmd,
+                                                    1, &curr_bank, 1);
+                       if (ret) {
+                               debug("SF: fail to read bank addr register\n");
+                               return ret;
+                       }
                }
                flash->bank_curr = curr_bank;
        } else {
@@ -346,6 +386,10 @@ static int spi_enable_wp_pin(struct spi_flash *flash)
 int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
 {
        u8 idcode[5];
+#ifdef CONFIG_SPI_GENERIC
+       u8 idcode_up[5];
+       u8 i;
+#endif
        int ret;
 
        /* Setup spi_slave */
@@ -361,6 +405,8 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
                return ret;
        }
 
+       if (spi->option == SF_DUAL_PARALLEL_FLASH)
+               spi->flags |= SPI_XFER_LOWER;
        /* Read the ID codes */
        ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
        if (ret) {
@@ -368,6 +414,23 @@ int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
                goto err_read_id;
        }
 
+#ifdef CONFIG_SPI_GENERIC
+       if (spi->option == SF_DUAL_PARALLEL_FLASH) {
+               spi->flags |= SPI_XFER_UPPER;
+               ret = spi_flash_cmd(spi, CMD_READ_ID, idcode_up,
+                                   sizeof(idcode_up));
+               if (ret) {
+                       printf("SF: Failed to get idcodes\n");
+                       goto err_read_id;
+               }
+               for (i = 0; i < sizeof(idcode); i++) {
+                       if (idcode[i] != idcode_up[i]) {
+                               printf("SF: Failed to get same idcodes\n");
+                               goto err_read_id;
+                       }
+               }
+       }
+#endif
 #ifdef DEBUG
        printf("SF: Got idcodes\n");
        print_buffer(0, idcode, 1, sizeof(idcode), 0);
index ae53ba54b8f20b8ab08695766a345686088ac5fc..7f2472b06c04c46d361a984c503e0c3d8deb54ca 100644 (file)
 #define SPI_XFER_MMAP_END      0x10    /* Memory Mapped End */
 #define SPI_XFER_ONCE          (SPI_XFER_BEGIN | SPI_XFER_END)
 #define SPI_XFER_U_PAGE        (1 << 5)
+#define SPI_XFER_STRIPE        (1 << 6)
+#define SPI_XFER_MASK  (3 << 8)
+#define SPI_XFER_LOWER (1 << 8)
+#define SPI_XFER_UPPER (2 << 8)
 
 /* SPI TX operation modes */
 #define SPI_OPM_TX_QPP         (1 << 0)
@@ -106,7 +110,7 @@ struct spi_slave {
        unsigned int max_write_size;
        void *memory_map;
        u8 option;
-       u8 flags;
+       u32 flags;
 };
 
 /**