]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
mtd: spi-nor: Added support for ISSI Serial NOR Flash
authorAmit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
Fri, 15 Mar 2019 15:08:22 +0000 (20:38 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Fri, 15 Mar 2019 16:39:46 +0000 (17:39 +0100)
For ISSI flash connected in dual parallel mode, the stripe
was getting enabled while writing configuration data to the
flashes.

So the configuration register of only one of the two flashes
was getting updated.

Due to this flash read/write operation was failing in dual
parallel mode.

This patch fixed the issue by disabling stripe while writing
configuration data to the flash in dual parallel mode.

Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/mtd/spi-nor/spi-nor.c

index 7ea83555864b0756ee2111378d3baa3023415092..308b4fe6c6ba262b27462991934ff06fce7b865b 100644 (file)
@@ -109,7 +109,11 @@ bool update_stripe(const u8 opcode)
            opcode ==  SPINOR_OP_SE ||
            opcode ==  SPINOR_OP_BE_32K_4B ||
            opcode ==  SPINOR_OP_SE_4B ||
-           opcode == SPINOR_OP_BE_4K_4B)
+           opcode == SPINOR_OP_BE_4K_4B ||
+           opcode ==  SPINOR_OP_WRSR ||
+           opcode ==  SPINOR_OP_WREAR ||
+           opcode ==  SPINOR_OP_BRWR ||
+           opcode ==  SPINOR_OP_WRSR2)
                return false;
 
        return true;
@@ -1426,13 +1430,17 @@ static const struct flash_info spi_nor_ids[] = {
        { "is25lp128f", INFO(0x9d6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
        { "is25wp128f", INFO(0x9d7018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
        { "is25lp256d", INFO(0x9d6019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
-       { "is25wp256d", INFO(0x9d7019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
+       { "is25wp256d", INFO(0x9d7019, 0, 64 * 1024, 512,
+                       SECT_4K | SPI_NOR_DUAL_READ |
+                       SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK |
+                       SPI_NOR_4B_OPCODES) },
        { "is25lp512m", INFO(0x9d601a, 0, 64 * 1024, 1024,
                        SECT_4K | SPI_NOR_DUAL_READ |
                        SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
        { "is25wp512m", INFO(0x9d701a, 0, 64 * 1024, 1024,
                        SECT_4K | SPI_NOR_DUAL_READ |
-                       SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
+                       SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK |
+                       SPI_NOR_4B_OPCODES) },
        { "is25cd512",  INFO(0x7f9d20, 0, 32 * 1024,   2, SECT_4K) },
        { "is25lq040b", INFO(0x9d4013, 0, 64 * 1024,   8,
                        SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
@@ -2716,6 +2724,9 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
        }
        params->size >>= 3; /* Convert to bytes. */
 
+       if (params->size > 0x1000000 && nor->addr_width == 3)
+               return -EINVAL;
+
        /* Fast Read settings. */
        for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_reads); i++) {
                const struct sfdp_bfpt_read *rd = &sfdp_bfpt_reads[i];
@@ -3000,11 +3011,6 @@ static int spi_nor_init_params(struct spi_nor *nor,
                        nor->addr_width = 0;
                        nor->mtd.erasesize = 0;
                } else {
-                       if ((JEDEC_MFR(info) == SNOR_MFR_ISSI) &&
-                           params->size >  OFFSET_16_MB) {
-                               nor->addr_width = 4;
-                               set_4byte(nor, info, 1);
-                       }
                        memcpy(params, &sfdp_params, sizeof(*params));
                }
        }
@@ -3121,7 +3127,15 @@ static int spi_nor_select_erase(struct spi_nor *nor,
        struct mtd_info *mtd = &nor->mtd;
 
        /* Do nothing if already configured from SFDP. */
+
+       /*
+        * For ISSI flashes with size > 16MB connected in dual
+        * parallel mode, the erasesize is set to sector size but
+        * erase_opcode is NULL, so to assign an erase_ opcode,
+        * !nor->isparallel check is added.
+        */
        if (mtd->erasesize &&
+           !nor->isparallel &&
            JEDEC_MFR(info) != SNOR_MFR_SPANSION)
                return 0;