]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
sf: Update the qspi dual parallel flash access logic
authorJagannadha Sutradharudu Teki <jaganna@xilinx.com>
Fri, 3 May 2013 09:32:24 +0000 (15:02 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Mon, 27 May 2013 11:21:19 +0000 (13:21 +0200)
Updated the xilinx qspi dual parallel flash access support
to use 3-byte addressing instead of 4-byte addressing used
from the mtd flash layer.

Instead of sending 4-byte addressing from mtd layer and
then the controller will again divide the offset addr by 2 and
convert the 4-byte address into 3-byte address, With this
new logic the mtd will serve the offset as offset by 2 and
send the 3-byte addressing to controller driver, as the
driver is configured as separate bus with two mem the
controller internal hardware algorithm will take care the
dual parallel functionality.

Below are the changes for dual parallel to work:
- mtd layer -> addr/2, page_size*2, nr_sectors/nr_blocks*2
- driver -> enable SEP_BUS[BIT:29],TWO_MEM[BIT:30] on LQSPI_CFG

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
drivers/mtd/spi/spansion.c
drivers/mtd/spi/spi_flash.c
drivers/mtd/spi/stmicro.c
drivers/mtd/spi/winbond.c
drivers/spi/zynq_qspips.c
include/spi_flash.h

index 28ecda6936bdf5f953f3fadedbaaf157fd0b9d47..09569ebefef700e83feb713862c20fe79f4180ba 100644 (file)
@@ -144,12 +144,11 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
        flash->page_size = 256;
        flash->sector_size = 256 * params->pages_per_sector;
 
-       /* address width is 4 for dual and 3 for single qspi */
+       /* page_size and nr_sectors are double for dual parallel qspi */
        if (flash->spi->is_dual == 2) {
-               flash->addr_width = 4;
+               flash->page_size *= 2;
                flash->size = flash->sector_size * (2 * params->nr_sectors);
        } else {
-               flash->addr_width = 3;
                flash->size = flash->sector_size * params->nr_sectors;
        }
 
index c7dc775a5de51f4b84b2a6567468b8072bbce2ba..7c8089f4419c8832cc2234c8540b06e219e57148 100644 (file)
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static void spi_flash_addr(struct spi_flash *flash,
-       unsigned long page_addr, unsigned long byte_addr, u8 *cmd)
+static void spi_flash_addr(unsigned long page_addr,
+                       unsigned long byte_addr, u8 *cmd)
 {
        /* cmd[0] is actual command */
-       if (flash->addr_width == 4) {
-               cmd[1] = page_addr >> 16;
-               cmd[2] = page_addr >> 8;
-               cmd[3] = page_addr;
-               cmd[4] = byte_addr;
-       } else {
-               cmd[1] = page_addr >> 8;
-               cmd[2] = page_addr;
-               cmd[3] = byte_addr;
-       }
+       cmd[1] = page_addr >> 8;
+       cmd[2] = page_addr;
+       cmd[3] = byte_addr;
 }
 
 static int spi_flash_read_write(struct spi_slave *spi,
@@ -82,7 +75,7 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
        unsigned long page_addr, byte_addr, page_size;
        size_t chunk_len, actual;
        int ret;
-       u8 cmd[flash->addr_width+1];
+       u8 cmd[4];
        u32 start;
        u8 bank_sel;
 
@@ -97,6 +90,9 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
 
        cmd[0] = CMD_PAGE_PROGRAM;
        for (actual = 0; actual < len; actual += chunk_len) {
+               if (flash->spi->is_dual == 2)
+                       offset /= 2;
+
                bank_sel = offset / SPI_FLASH_16MB_BOUN;
 
                ret = spi_flash_cmd_bankaddr_write(flash,
@@ -114,11 +110,10 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
                if (flash->spi->max_write_size)
                        chunk_len = min(chunk_len, flash->spi->max_write_size);
 
-               spi_flash_addr(flash, page_addr, byte_addr, cmd);
+               spi_flash_addr(page_addr, byte_addr, cmd);
 
-               debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x0x%02x } \
-                       chunk_len = %zu\n", buf + actual, cmd[0], cmd[1],
-                       cmd[2], cmd[3], cmd[4], chunk_len);
+               debug("PP: 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);
 
                ret = spi_flash_cmd_write_enable(flash);
                if (ret < 0) {
@@ -164,7 +159,7 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
                size_t len, void *data)
 {
        unsigned long page_addr, page_size, byte_addr;
-       u8 cmd[flash->addr_width+2];
+       u8 cmd[5];
        u8 bank_sel;
        u32 remain_len, read_len;
        int ret = -1;
@@ -178,6 +173,9 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
        cmd[sizeof(cmd)-1] = 0x00;
 
        while (len) {
+               if (flash->spi->is_dual == 2)
+                       offset /= 2;
+
                bank_sel = offset / SPI_FLASH_16MB_BOUN;
                remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset);
 
@@ -196,7 +194,7 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
                page_addr = (offset & SPI_FLASH_16MB_MASK) / page_size;
                byte_addr = (offset & SPI_FLASH_16MB_MASK) % page_size;
 
-               spi_flash_addr(flash, page_addr, byte_addr, cmd);
+               spi_flash_addr(page_addr, byte_addr, cmd);
 
                ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
                                                        data, read_len);
@@ -261,7 +259,7 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
        u32 start, end, erase_size;
        int ret;
        unsigned long page_addr;
-       u8 cmd[flash->addr_width+1];
+       u8 cmd[4];
        u8 bank_sel;
 
        erase_size = flash->sector_size;
@@ -285,6 +283,8 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
 
        while (offset < end) {
                bank_sel = offset / SPI_FLASH_16MB_BOUN;
+               if (flash->spi->is_dual == 2)
+                       bank_sel -= ((flash->size / 2) / SPI_FLASH_16MB_BOUN);
 
                ret = spi_flash_cmd_bankaddr_write(flash,
                                        bank_sel, flash->idcode0);
@@ -294,10 +294,10 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
                }
 
                page_addr = (offset & SPI_FLASH_16MB_MASK) / flash->page_size;
-               spi_flash_addr(flash, page_addr, 0, cmd);
+               spi_flash_addr(page_addr, 0, cmd);
 
-               debug("SF: erase %2x %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
-                       cmd[2], cmd[3], cmd[4], offset);
+               debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
+                     cmd[2], cmd[3], offset);
 
                ret = spi_flash_cmd_write_enable(flash);
                if (ret)
@@ -567,8 +567,10 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
        puts("\n");
 
        flash->idcode0 = *idp;
-       if ((flash->spi->is_dual == 0) &&
-           (flash->size > SPI_FLASH_16MB_BOUN)) {
+       if (((flash->spi->is_dual == 0) &&
+                       (flash->size > SPI_FLASH_16MB_BOUN)) ||
+                       ((flash->spi->is_dual == 2) &&
+                       ((flash->size / 2) > SPI_FLASH_16MB_BOUN))) {
                if (spi_flash_cmd_bankaddr_read(flash, &curr_bank,
                                                flash->idcode0)) {
                        debug("SF: fail to read bank addr register\n");
index cf4601b3befe358157219399fa526c36120682aa..eae4227f72f19417d5d8754e03effa9aaf394135 100644 (file)
@@ -209,12 +209,11 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
        flash->page_size = 256;
        flash->sector_size = 256 * params->pages_per_sector;
 
-       /* address width is 4 for dual and 3 for single qspi */
+       /* page_size and nr_sectors are double for dual parallel qspi */
        if (flash->spi->is_dual == 2) {
-               flash->addr_width = 4;
+               flash->page_size *= 2;
                flash->size = flash->sector_size * (2 * params->nr_sectors);
        } else {
-               flash->addr_width = 3;
                flash->size = flash->sector_size * params->nr_sectors;
        }
 
index 3b4be7f69855355af83515e92717aec9d4ba8d49..d7eb7f1e6303ef3aad3178fe72095a0bd2703a64 100644 (file)
@@ -111,12 +111,11 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
        flash->page_size = 256;
        flash->sector_size = 4096;
 
-       /* address width is 4 for dual and 3 for single qspi */
+       /* page_size and nr_blocks are double for dual parallel qspi */
        if (flash->spi->is_dual == 2) {
-               flash->addr_width = 4;
+               flash->page_size *= 2;
                flash->size = 4096 * 16 * (2 * params->nr_blocks);
        } else {
-               flash->addr_width = 3;
                flash->size = 4096 * 16 * params->nr_blocks;
        }
 
index 91aa7fcd094387dd4714d35f7cc50f228f5367d7..5288711ee3e06ab59c2bac7b7bd019fb016759b1 100644 (file)
@@ -657,32 +657,6 @@ static int xqspips_start_transfer(struct spi_device *qspi,
                xqspi->curr_inst = &flash_inst[index];
                xqspi->inst_response = 1;
 
-               /*
-                * In case of dual memories, convert 25 bit address to 24 bit
-                * address before transmitting to the 2 memories
-                */
-               if ((xqspi->is_dual == MODE_DUAL_PARALLEL) &&
-                   ((instruction == XQSPIPS_FLASH_OPCODE_PP) ||
-                   (instruction == XQSPIPS_FLASH_OPCODE_SE) ||
-                   (instruction == XQSPIPS_FLASH_OPCODE_BE_32K) ||
-                   (instruction == XQSPIPS_FLASH_OPCODE_BE_4K) ||
-                   (instruction == XQSPIPS_FLASH_OPCODE_BE) ||
-                   (instruction == XQSPIPS_FLASH_OPCODE_NORM_READ) ||
-                   (instruction == XQSPIPS_FLASH_OPCODE_FAST_READ) ||
-                   (instruction == XQSPIPS_FLASH_OPCODE_DUAL_READ) ||
-                   (instruction == XQSPIPS_FLASH_OPCODE_QUAD_READ))) {
-
-                       u8 *ptr = (u8 *) (xqspi->txbuf);
-                       data = ((u32) ptr[1] << 24) | ((u32) ptr[2] << 16) |
-                               ((u32) ptr[3] << 8) | ((u32) ptr[4]);
-                       data = data/2;
-                       ptr[1] = (u8) (data >> 16);
-                       ptr[2] = (u8) (data >> 8);
-                       ptr[3] = (u8) (data);
-                       xqspi->bytes_to_transfer -= 1;
-                       xqspi->bytes_to_receive -= 1;
-               }
-
                /* Get the instruction */
                data = 0;
                xqspips_copy_write_data(xqspi, &data,
index 2475be5de36b4fb026431aeb03290c0e5765d28e..88b302a4a6f566bc7f09cc0e6bc05e6d63c4f92d 100644 (file)
@@ -38,8 +38,6 @@ struct spi_flash {
        u32             page_size;
        /* Erase (sector) size */
        u32             sector_size;
-       /* To find whether single/dual spi device */
-       u8              addr_width;
        /* ID code0 */
        u8              idcode0;
        /* Current bank */