]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'nand/for-5.1' of git://git.infradead.org/linux-mtd into mtd/next
authorBoris Brezillon <boris.brezillon@collabora.com>
Mon, 25 Feb 2019 08:28:54 +0000 (09:28 +0100)
committerBoris Brezillon <boris.brezillon@collabora.com>
Mon, 25 Feb 2019 08:28:54 +0000 (09:28 +0100)
NAND core changes:
- Fourth batch of fixes/cleanup to the raw NAND core impacting various
  controller drivers (Sunxi, Marvell, MTK, TMIO, OMAP2).
- Checking the return code of nand_reset() and nand_readid_op().
- Removing ->legacy.erase and single_erase().
- Simplifying the locking.
- Several implicit fall through annotations.

Raw NAND controllers drivers changes:
- Fixing various possible object reference leaks (MTK, JZ4780, Atmel).
- ST:
  * Adding support for STM32 FMC2 NAND flash controller.
- Meson:
  * Adding support for Amlogic NAND flash controller.
- Denali:
  * Several cleanup patches.
- Sunxi:
  * Several cleanup patches.
- FSMC:
  * Disabling NAND on remove().
  * Resetting NAND timings on resume().

SPI-NAND drivers changes:
- Toshiba:
  * Adding support for all Toshiba products.
- Macronix:
  * Fixing ECC status read.
- Gigadevice:
  * Adding support for GD5F1GQ4UExxG.

16 files changed:
Documentation/devicetree/bindings/mtd/cadence-quadspi.txt
Documentation/devicetree/bindings/mtd/mtk-quadspi.txt
MAINTAINERS
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/gen_probe.c
drivers/mtd/devices/docg3.c
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/mtdram.c
drivers/mtd/lpddr/qinfo_probe.c
drivers/mtd/mtdcore.c
drivers/mtd/spi-nor/Kconfig
drivers/mtd/spi-nor/Makefile
drivers/mtd/spi-nor/cadence-quadspi.c
drivers/mtd/spi-nor/mtk-quadspi.c
drivers/mtd/spi-nor/spi-nor.c
include/linux/mtd/spi-nor.h

index bb2075df9b3826dd813dd23567ac470ffed5144e..4345c3a6f5300725d72b5dd3c93f6e9a7c82ddb2 100644 (file)
@@ -4,6 +4,7 @@ Required properties:
 - compatible : should be one of the following:
        Generic default - "cdns,qspi-nor".
        For TI 66AK2G SoC - "ti,k2g-qspi", "cdns,qspi-nor".
+       For TI AM654 SoC  - "ti,am654-ospi", "cdns,qspi-nor".
 - reg : Contains two entries, each of which is a tuple consisting of a
        physical address and length. The first entry is the address and
        length of the controller register set. The second entry is the
index 56d3668e2c50e808fca1274436d151951f4ee6a1..a12e3b5c495d969eb7cef2b99f1cef25990e4bd9 100644 (file)
@@ -1,4 +1,4 @@
-* Serial NOR flash controller for MTK MT81xx (and similar)
+* Serial NOR flash controller for MediaTek SoCs
 
 Required properties:
 - compatible:    For mt8173, compatible should be "mediatek,mt8173-nor",
@@ -10,6 +10,7 @@ Required properties:
                  "mediatek,mt2712-nor", "mediatek,mt8173-nor"
                  "mediatek,mt7622-nor", "mediatek,mt8173-nor"
                  "mediatek,mt7623-nor", "mediatek,mt8173-nor"
+                 "mediatek,mt7629-nor", "mediatek,mt8173-nor"
                  "mediatek,mt8173-nor"
 - reg:                   physical base address and length of the controller's register
 - clocks:        the phandle of the clocks needed by the nor controller
index e6b902c7c8287c6c126060382b2da8218121fee3..0a516c843e77329699648f8c420ffd111551590c 100644 (file)
@@ -14310,6 +14310,7 @@ F:      arch/arm/mach-spear/
 
 SPI NOR SUBSYSTEM
 M:     Marek Vasut <marek.vasut@gmail.com>
+M:     Tudor Ambarus <tudor.ambarus@microchip.com>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
 Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
index 6e8e7b1bb34b65a4196c7979aa8d1ca10a9f2f07..79a53cb8507b69a6102c8ac7e9d7716eb58dc021 100644 (file)
@@ -756,7 +756,8 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
                }
 
                numvirtchips = cfi->numchips * numparts;
-               newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL);
+               newcfi = kmalloc(struct_size(newcfi, chips, numvirtchips),
+                                GFP_KERNEL);
                if (!newcfi)
                        return -ENOMEM;
                shared = kmalloc_array(cfi->numchips,
index 837b04ab96a9c526f19699655cfa9ee174bd190b..839ed40625d6bbd94c7d1de5c6aa5260f3fa4388 100644 (file)
@@ -135,7 +135,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
         * our caller, and copy the appropriate data into them.
         */
 
-       retcfi = kmalloc(sizeof(struct cfi_private) + cfi.numchips * sizeof(struct flchip), GFP_KERNEL);
+       retcfi = kmalloc(struct_size(retcfi, chips, cfi.numchips), GFP_KERNEL);
 
        if (!retcfi) {
                kfree(cfi.cfiq);
index 4c94fc0966964b8c15aefc086cd5ecb8174f7d27..7754803e34639a79bbe49c16617a03339acb097a 100644 (file)
@@ -1767,8 +1767,8 @@ static int __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
 
        switch (chip_id) {
        case DOC_CHIPID_G3:
-               mtd->name = kasprintf(GFP_KERNEL, "docg3.%d",
-                                     docg3->device_id);
+               mtd->name = devm_kasprintf(docg3->dev, GFP_KERNEL, "docg3.%d",
+                                          docg3->device_id);
                if (!mtd->name)
                        return -ENOMEM;
                docg3->max_block = 2047;
@@ -1872,7 +1872,7 @@ doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev)
 nomem2:
        kfree(docg3);
 nomem1:
-       return ERR_PTR(ret);
+       return ret ? ERR_PTR(ret) : NULL;
 }
 
 /**
@@ -1886,7 +1886,6 @@ static void doc_release_device(struct mtd_info *mtd)
        mtd_device_unregister(mtd);
        kfree(docg3->bbt);
        kfree(docg3);
-       kfree(mtd->name);
        kfree(mtd);
 }
 
index c4a1d04b8c800d1b090e99dc9975025d4b61009c..651bab6d4e31bea8c68f0461a3aefedf21e01fc7 100644 (file)
@@ -195,7 +195,14 @@ static int m25p_probe(struct spi_mem *spimem)
        spi_mem_set_drvdata(spimem, flash);
        flash->spimem = spimem;
 
-       if (spi->mode & SPI_RX_QUAD) {
+       if (spi->mode & SPI_RX_OCTAL) {
+               hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
+
+               if (spi->mode & SPI_TX_OCTAL)
+                       hwcaps.mask |= (SNOR_HWCAPS_READ_1_8_8 |
+                                       SNOR_HWCAPS_PP_1_1_8 |
+                                       SNOR_HWCAPS_PP_1_8_8);
+       } else if (spi->mode & SPI_RX_QUAD) {
                hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
 
                if (spi->mode & SPI_TX_QUAD)
index 46238796145ffad93092197b7dc76fa0ae9c91ef..1c97fabc4bf9bf8739b90a696d05bde14f0de21c 100644 (file)
@@ -24,14 +24,12 @@ static unsigned long writebuf_size = 64;
 #define MTDRAM_TOTAL_SIZE (total_size * 1024)
 #define MTDRAM_ERASE_SIZE (erase_size * 1024)
 
-#ifdef MODULE
 module_param(total_size, ulong, 0);
 MODULE_PARM_DESC(total_size, "Total device size in KiB");
 module_param(erase_size, ulong, 0);
 MODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
 module_param(writebuf_size, ulong, 0);
 MODULE_PARM_DESC(writebuf_size, "Device write buf size in Bytes (Default: 64)");
-#endif
 
 // We could store these in the mtd structure, but we only support 1 device..
 static struct mtd_info *mtd_info;
index 69f2112340b19dc94639ff90bd87114490767168..175bdc3b72f4efb56b56221ae644122642f7bfe7 100644 (file)
@@ -181,8 +181,8 @@ static struct lpddr_private *lpddr_probe_chip(struct map_info *map)
        lpddr.numchips = 1;
 
        numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum;
-       retlpddr = kzalloc(sizeof(struct lpddr_private) +
-                       numvirtchips * sizeof(struct flchip), GFP_KERNEL);
+       retlpddr = kzalloc(struct_size(retlpddr, chips, numvirtchips),
+                          GFP_KERNEL);
        if (!retlpddr)
                return NULL;
 
index 21e3cdc04036dd0b2622d0a3c9aec1a5dbd545af..c69b33cd18f3548c7f524e0fd79ea22edb286f39 100644 (file)
@@ -155,7 +155,6 @@ static ssize_t mtd_flags_show(struct device *dev,
        struct mtd_info *mtd = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags);
-
 }
 static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL);
 
@@ -166,7 +165,6 @@ static ssize_t mtd_size_show(struct device *dev,
 
        return snprintf(buf, PAGE_SIZE, "%llu\n",
                (unsigned long long)mtd->size);
-
 }
 static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL);
 
@@ -176,7 +174,6 @@ static ssize_t mtd_erasesize_show(struct device *dev,
        struct mtd_info *mtd = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize);
-
 }
 static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL);
 
@@ -186,7 +183,6 @@ static ssize_t mtd_writesize_show(struct device *dev,
        struct mtd_info *mtd = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize);
-
 }
 static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL);
 
@@ -197,7 +193,6 @@ static ssize_t mtd_subpagesize_show(struct device *dev,
        unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft;
 
        return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize);
-
 }
 static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL);
 
@@ -207,7 +202,6 @@ static ssize_t mtd_oobsize_show(struct device *dev,
        struct mtd_info *mtd = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize);
-
 }
 static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL);
 
@@ -226,7 +220,6 @@ static ssize_t mtd_numeraseregions_show(struct device *dev,
        struct mtd_info *mtd = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions);
-
 }
 static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show,
        NULL);
@@ -237,7 +230,6 @@ static ssize_t mtd_name_show(struct device *dev,
        struct mtd_info *mtd = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name);
-
 }
 static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL);
 
@@ -559,6 +551,14 @@ int add_mtd_device(struct mtd_info *mtd)
 
        BUG_ON(mtd->writesize == 0);
 
+       /*
+        * MTD drivers should implement ->_{write,read}() or
+        * ->_{write,read}_oob(), but not both.
+        */
+       if (WARN_ON((mtd->_write && mtd->_write_oob) ||
+                   (mtd->_read && mtd->_read_oob)))
+               return -EINVAL;
+
        if (WARN_ON((!mtd->erasesize || !mtd->_erase) &&
                    !(mtd->flags & MTD_NO_ERASE)))
                return -EINVAL;
@@ -1089,67 +1089,32 @@ EXPORT_SYMBOL_GPL(mtd_get_unmapped_area);
 int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
             u_char *buf)
 {
-       int ret_code;
-       *retlen = 0;
-       if (from < 0 || from >= mtd->size || len > mtd->size - from)
-               return -EINVAL;
-       if (!len)
-               return 0;
+       struct mtd_oob_ops ops = {
+               .len = len,
+               .datbuf = buf,
+       };
+       int ret;
 
-       ledtrig_mtd_activity();
-       /*
-        * In the absence of an error, drivers return a non-negative integer
-        * representing the maximum number of bitflips that were corrected on
-        * any one ecc region (if applicable; zero otherwise).
-        */
-       if (mtd->_read) {
-               ret_code = mtd->_read(mtd, from, len, retlen, buf);
-       } else if (mtd->_read_oob) {
-               struct mtd_oob_ops ops = {
-                       .len = len,
-                       .datbuf = buf,
-               };
-
-               ret_code = mtd->_read_oob(mtd, from, &ops);
-               *retlen = ops.retlen;
-       } else {
-               return -ENOTSUPP;
-       }
+       ret = mtd_read_oob(mtd, from, &ops);
+       *retlen = ops.retlen;
 
-       if (unlikely(ret_code < 0))
-               return ret_code;
-       if (mtd->ecc_strength == 0)
-               return 0;       /* device lacks ecc */
-       return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_read);
 
 int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
              const u_char *buf)
 {
-       *retlen = 0;
-       if (to < 0 || to >= mtd->size || len > mtd->size - to)
-               return -EINVAL;
-       if ((!mtd->_write && !mtd->_write_oob) ||
-           !(mtd->flags & MTD_WRITEABLE))
-               return -EROFS;
-       if (!len)
-               return 0;
-       ledtrig_mtd_activity();
+       struct mtd_oob_ops ops = {
+               .len = len,
+               .datbuf = (u8 *)buf,
+       };
+       int ret;
 
-       if (!mtd->_write) {
-               struct mtd_oob_ops ops = {
-                       .len = len,
-                       .datbuf = (u8 *)buf,
-               };
-               int ret;
+       ret = mtd_write_oob(mtd, to, &ops);
+       *retlen = ops.retlen;
 
-               ret = mtd->_write_oob(mtd, to, &ops);
-               *retlen = ops.retlen;
-               return ret;
-       }
-
-       return mtd->_write(mtd, to, len, retlen, buf);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_write);
 
index 44fe8018733c283e91ae30994bdf2dd21183c558..414e88749b1fa5e5fb9f7b1dd49b3d8f7435190c 100644 (file)
@@ -7,14 +7,6 @@ menuconfig MTD_SPI_NOR
 
 if MTD_SPI_NOR
 
-config MTD_MT81xx_NOR
-       tristate "Mediatek MT81xx SPI NOR flash controller"
-       depends on HAS_IOMEM
-       help
-         This enables access to SPI NOR flash, using MT81xx SPI NOR flash
-         controller. This controller does not support generic SPI BUS, it only
-         supports SPI NOR Flash.
-
 config MTD_SPI_NOR_USE_4K_SECTORS
        bool "Use small 4096 B erase sectors"
        default y
@@ -66,6 +58,14 @@ config SPI_HISI_SFC
        help
          This enables support for hisilicon SPI-NOR flash controller.
 
+config SPI_MTK_QUADSPI
+       tristate "MediaTek Quad SPI controller"
+       depends on HAS_IOMEM
+       help
+         This enables support for the Quad SPI controller in master mode.
+         This controller does not support generic SPI. It only supports
+         SPI NOR.
+
 config SPI_NXP_SPIFI
        tristate "NXP SPI Flash Interface (SPIFI)"
        depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
index a552efd22958238125cc1bc8d2136e790ccb1cf5..4e4d4005d7a62d33cb80f5e64a8e909958bb1f24 100644 (file)
@@ -4,7 +4,7 @@ obj-$(CONFIG_SPI_ASPEED_SMC)    += aspeed-smc.o
 obj-$(CONFIG_SPI_CADENCE_QUADSPI)      += cadence-quadspi.o
 obj-$(CONFIG_SPI_FSL_QUADSPI)  += fsl-quadspi.o
 obj-$(CONFIG_SPI_HISI_SFC)     += hisi-sfc.o
-obj-$(CONFIG_MTD_MT81xx_NOR)    += mtk-quadspi.o
+obj-$(CONFIG_SPI_MTK_QUADSPI)    += mtk-quadspi.o
 obj-$(CONFIG_SPI_NXP_SPIFI)    += nxp-spifi.o
 obj-$(CONFIG_SPI_INTEL_SPI)    += intel-spi.o
 obj-$(CONFIG_SPI_INTEL_SPI_PCI)        += intel-spi-pci.o
index 04cedd3a2bf6634c5d1f05ef3d27ba302d12935f..792628750eeca8b4de6a95bdea96bb83378a021d 100644 (file)
 /* Quirks */
 #define CQSPI_NEEDS_WR_DELAY           BIT(0)
 
+/* Capabilities mask */
+#define CQSPI_BASE_HWCAPS_MASK                                 \
+       (SNOR_HWCAPS_READ | SNOR_HWCAPS_READ_FAST |             \
+       SNOR_HWCAPS_READ_1_1_2 | SNOR_HWCAPS_READ_1_1_4 |       \
+       SNOR_HWCAPS_PP)
+
 struct cqspi_st;
 
 struct cqspi_flash_pdata {
@@ -93,6 +99,11 @@ struct cqspi_st {
        struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT];
 };
 
+struct cqspi_driver_platdata {
+       u32 hwcaps_mask;
+       u8 quirks;
+};
+
 /* Operation timeout value */
 #define CQSPI_TIMEOUT_MS                       500
 #define CQSPI_READ_TIMEOUT_MS                  10
@@ -101,6 +112,7 @@ struct cqspi_st {
 #define CQSPI_INST_TYPE_SINGLE                 0
 #define CQSPI_INST_TYPE_DUAL                   1
 #define CQSPI_INST_TYPE_QUAD                   2
+#define CQSPI_INST_TYPE_OCTAL                  3
 
 #define CQSPI_DUMMY_CLKS_PER_BYTE              8
 #define CQSPI_DUMMY_BYTES_MAX                  4
@@ -418,9 +430,10 @@ static int cqspi_command_write(struct spi_nor *nor, const u8 opcode,
        void __iomem *reg_base = cqspi->iobase;
        unsigned int reg;
        unsigned int data;
+       u32 write_len;
        int ret;
 
-       if (n_tx > 4 || (n_tx && !txbuf)) {
+       if (n_tx > CQSPI_STIG_DATA_LEN_MAX || (n_tx && !txbuf)) {
                dev_err(nor->dev,
                        "Invalid input argument, cmdlen %d txbuf 0x%p\n",
                        n_tx, txbuf);
@@ -433,10 +446,18 @@ static int cqspi_command_write(struct spi_nor *nor, const u8 opcode,
                reg |= ((n_tx - 1) & CQSPI_REG_CMDCTRL_WR_BYTES_MASK)
                        << CQSPI_REG_CMDCTRL_WR_BYTES_LSB;
                data = 0;
-               memcpy(&data, txbuf, n_tx);
+               write_len = (n_tx > 4) ? 4 : n_tx;
+               memcpy(&data, txbuf, write_len);
+               txbuf += write_len;
                writel(data, reg_base + CQSPI_REG_CMDWRITEDATALOWER);
-       }
 
+               if (n_tx > 4) {
+                       data = 0;
+                       write_len = n_tx - 4;
+                       memcpy(&data, txbuf, write_len);
+                       writel(data, reg_base + CQSPI_REG_CMDWRITEDATAUPPER);
+               }
+       }
        ret = cqspi_exec_flash_cmd(cqspi, reg);
        return ret;
 }
@@ -911,6 +932,9 @@ static int cqspi_set_protocol(struct spi_nor *nor, const int read)
                case SNOR_PROTO_1_1_4:
                        f_pdata->data_width = CQSPI_INST_TYPE_QUAD;
                        break;
+               case SNOR_PROTO_1_1_8:
+                       f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
+                       break;
                default:
                        return -EINVAL;
                }
@@ -1213,21 +1237,23 @@ static void cqspi_request_mmap_dma(struct cqspi_st *cqspi)
 
 static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
 {
-       const struct spi_nor_hwcaps hwcaps = {
-               .mask = SNOR_HWCAPS_READ |
-                       SNOR_HWCAPS_READ_FAST |
-                       SNOR_HWCAPS_READ_1_1_2 |
-                       SNOR_HWCAPS_READ_1_1_4 |
-                       SNOR_HWCAPS_PP,
-       };
        struct platform_device *pdev = cqspi->pdev;
        struct device *dev = &pdev->dev;
+       const struct cqspi_driver_platdata *ddata;
+       struct spi_nor_hwcaps hwcaps;
        struct cqspi_flash_pdata *f_pdata;
        struct spi_nor *nor;
        struct mtd_info *mtd;
        unsigned int cs;
        int i, ret;
 
+       ddata = of_device_get_match_data(dev);
+       if (!ddata) {
+               dev_err(dev, "Couldn't find driver data\n");
+               return -EINVAL;
+       }
+       hwcaps.mask = ddata->hwcaps_mask;
+
        /* Get flash device data */
        for_each_available_child_of_node(dev->of_node, np) {
                ret = of_property_read_u32(np, "reg", &cs);
@@ -1310,7 +1336,7 @@ static int cqspi_probe(struct platform_device *pdev)
        struct cqspi_st *cqspi;
        struct resource *res;
        struct resource *res_ahb;
-       unsigned long data;
+       const struct cqspi_driver_platdata *ddata;
        int ret;
        int irq;
 
@@ -1377,8 +1403,8 @@ static int cqspi_probe(struct platform_device *pdev)
        }
 
        cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk);
-       data  = (unsigned long)of_device_get_match_data(dev);
-       if (data & CQSPI_NEEDS_WR_DELAY)
+       ddata  = of_device_get_match_data(dev);
+       if (ddata && (ddata->quirks & CQSPI_NEEDS_WR_DELAY))
                cqspi->wr_delay = 5 * DIV_ROUND_UP(NSEC_PER_SEC,
                                                   cqspi->master_ref_clk_hz);
 
@@ -1460,14 +1486,32 @@ static const struct dev_pm_ops cqspi__dev_pm_ops = {
 #define CQSPI_DEV_PM_OPS       NULL
 #endif
 
+static const struct cqspi_driver_platdata cdns_qspi = {
+       .hwcaps_mask = CQSPI_BASE_HWCAPS_MASK,
+};
+
+static const struct cqspi_driver_platdata k2g_qspi = {
+       .hwcaps_mask = CQSPI_BASE_HWCAPS_MASK,
+       .quirks = CQSPI_NEEDS_WR_DELAY,
+};
+
+static const struct cqspi_driver_platdata am654_ospi = {
+       .hwcaps_mask = CQSPI_BASE_HWCAPS_MASK | SNOR_HWCAPS_READ_1_1_8,
+       .quirks = CQSPI_NEEDS_WR_DELAY,
+};
+
 static const struct of_device_id cqspi_dt_ids[] = {
        {
                .compatible = "cdns,qspi-nor",
-               .data = (void *)0,
+               .data = &cdns_qspi,
        },
        {
                .compatible = "ti,k2g-qspi",
-               .data = (void *)CQSPI_NEEDS_WR_DELAY,
+               .data = &k2g_qspi,
+       },
+       {
+               .compatible = "ti,am654-ospi",
+               .data = &am654_ospi,
        },
        { /* end of table */ }
 };
index 5442993b71ff2f7da4e06448cd5ec8a8130e4115..d9eed6844ba11aea76d87bf295946b71127a27ca 100644 (file)
@@ -431,7 +431,8 @@ static int mtk_nor_init(struct mtk_nor *mtk_nor,
                        struct device_node *flash_node)
 {
        const struct spi_nor_hwcaps hwcaps = {
-               .mask = SNOR_HWCAPS_READ_FAST |
+               .mask = SNOR_HWCAPS_READ |
+                       SNOR_HWCAPS_READ_FAST |
                        SNOR_HWCAPS_READ_1_1_2 |
                        SNOR_HWCAPS_PP,
        };
index 6e13bbd1aaa508308790c07e914dedb011b8d591..fae147452aff34994a7bd562c2bc74d97b5c4046 100644 (file)
@@ -68,7 +68,7 @@ enum spi_nor_read_command_index {
        SNOR_CMD_READ_4_4_4,
        SNOR_CMD_READ_1_4_4_DTR,
 
-       /* Octo SPI */
+       /* Octal SPI */
        SNOR_CMD_READ_1_1_8,
        SNOR_CMD_READ_1_8_8,
        SNOR_CMD_READ_8_8_8,
@@ -85,7 +85,7 @@ enum spi_nor_pp_command_index {
        SNOR_CMD_PP_1_4_4,
        SNOR_CMD_PP_4_4_4,
 
-       /* Octo SPI */
+       /* Octal SPI */
        SNOR_CMD_PP_1_1_8,
        SNOR_CMD_PP_1_8_8,
        SNOR_CMD_PP_8_8_8,
@@ -278,6 +278,7 @@ struct flash_info {
 #define NO_CHIP_ERASE          BIT(12) /* Chip does not support chip erase */
 #define SPI_NOR_SKIP_SFDP      BIT(13) /* Skip parsing of SFDP tables */
 #define USE_CLSR               BIT(14) /* use CLSR command */
+#define SPI_NOR_OCTAL_READ     BIT(15) /* Flash supports Octal Read */
 
        /* Part specific fixup hooks. */
        const struct spi_nor_fixups *fixups;
@@ -398,6 +399,8 @@ static u8 spi_nor_convert_3to4_read(u8 opcode)
                { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B },
                { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B },
                { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B },
+               { SPINOR_OP_READ_1_1_8, SPINOR_OP_READ_1_1_8_4B },
+               { SPINOR_OP_READ_1_8_8, SPINOR_OP_READ_1_8_8_4B },
 
                { SPINOR_OP_READ_1_1_1_DTR,     SPINOR_OP_READ_1_1_1_DTR_4B },
                { SPINOR_OP_READ_1_2_2_DTR,     SPINOR_OP_READ_1_2_2_DTR_4B },
@@ -414,6 +417,8 @@ static u8 spi_nor_convert_3to4_program(u8 opcode)
                { SPINOR_OP_PP,         SPINOR_OP_PP_4B },
                { SPINOR_OP_PP_1_1_4,   SPINOR_OP_PP_1_1_4_4B },
                { SPINOR_OP_PP_1_4_4,   SPINOR_OP_PP_1_4_4_4B },
+               { SPINOR_OP_PP_1_1_8,   SPINOR_OP_PP_1_1_8_4B },
+               { SPINOR_OP_PP_1_8_8,   SPINOR_OP_PP_1_8_8_4B },
        };
 
        return spi_nor_convert_opcode(opcode, spi_nor_3to4_program,
@@ -1740,7 +1745,11 @@ static const struct flash_info spi_nor_ids[] = {
        { "en25q32b",   INFO(0x1c3016, 0, 64 * 1024,   64, 0) },
        { "en25p64",    INFO(0x1c2017, 0, 64 * 1024,  128, 0) },
        { "en25q64",    INFO(0x1c3017, 0, 64 * 1024,  128, SECT_4K) },
+       { "en25q80a",   INFO(0x1c3014, 0, 64 * 1024,   16,
+                       SECT_4K | SPI_NOR_DUAL_READ) },
        { "en25qh32",   INFO(0x1c7016, 0, 64 * 1024,   64, 0) },
+       { "en25qh64",   INFO(0x1c7017, 0, 64 * 1024,  128,
+                       SECT_4K | SPI_NOR_DUAL_READ) },
        { "en25qh128",  INFO(0x1c7018, 0, 64 * 1024,  256, 0) },
        { "en25qh256",  INFO(0x1c7019, 0, 64 * 1024,  512, 0) },
        { "en25s64",    INFO(0x1c3817, 0, 64 * 1024,  128, SECT_4K) },
@@ -1836,6 +1845,8 @@ static const struct flash_info spi_nor_ids[] = {
        { "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
        { "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
        { "mx25u2033e",  INFO(0xc22532, 0, 64 * 1024,   4, SECT_4K) },
+       { "mx25u3235f",  INFO(0xc22536, 0, 64 * 1024,  64,
+                        SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
        { "mx25u4035",   INFO(0xc22533, 0, 64 * 1024,   8, SECT_4K) },
        { "mx25u8035",   INFO(0xc22534, 0, 64 * 1024,  16, SECT_4K) },
        { "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
@@ -1847,6 +1858,8 @@ static const struct flash_info spi_nor_ids[] = {
                         SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
                         .fixups = &mx25l25635_fixups },
        { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
+       { "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
+                        SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
        { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
        { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
        { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
@@ -1872,7 +1885,8 @@ static const struct flash_info spi_nor_ids[] = {
        /* Micron */
        {
                "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
-                       SECT_4K | USE_FSR | SPI_NOR_4B_OPCODES)
+                       SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
+                       SPI_NOR_4B_OPCODES)
        },
 
        /* PMC */
@@ -1885,13 +1899,17 @@ static const struct flash_info spi_nor_ids[] = {
         */
        { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
        { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+       { "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64,
+                       SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
+       { "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256,
+                       SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
        { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
        { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
-       { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
+       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
+       { "s25fs512s",  INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
        { "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
        { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
        { "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
-       { "s25fl128s",  INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
        { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
        { "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
        { "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8, 0) },
@@ -3591,6 +3609,13 @@ static int spi_nor_init_params(struct spi_nor *nor,
                                          SNOR_PROTO_1_1_4);
        }
 
+       if (info->flags & SPI_NOR_OCTAL_READ) {
+               params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
+               spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_8],
+                                         0, 8, SPINOR_OP_READ_1_1_8,
+                                         SNOR_PROTO_1_1_8);
+       }
+
        /* Page Program settings. */
        params->hwcaps.mask |= SNOR_HWCAPS_PP;
        spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
index fa2d89e38e403dda8107c84d24fb9c8a5d9094bc..b3d360b0ee3d79881c45509a17a46fa91e24960e 100644 (file)
 #define SPINOR_OP_READ_1_2_2   0xbb    /* Read data bytes (Dual I/O SPI) */
 #define SPINOR_OP_READ_1_1_4   0x6b    /* Read data bytes (Quad Output SPI) */
 #define SPINOR_OP_READ_1_4_4   0xeb    /* Read data bytes (Quad I/O SPI) */
+#define SPINOR_OP_READ_1_1_8   0x8b    /* Read data bytes (Octal Output SPI) */
+#define SPINOR_OP_READ_1_8_8   0xcb    /* Read data bytes (Octal I/O SPI) */
 #define SPINOR_OP_PP           0x02    /* Page program (up to 256 bytes) */
 #define SPINOR_OP_PP_1_1_4     0x32    /* Quad page program */
 #define SPINOR_OP_PP_1_4_4     0x38    /* Quad page program */
+#define SPINOR_OP_PP_1_1_8     0x82    /* Octal page program */
+#define SPINOR_OP_PP_1_8_8     0xc2    /* Octal page program */
 #define SPINOR_OP_BE_4K                0x20    /* Erase 4KiB block */
 #define SPINOR_OP_BE_4K_PMC    0xd7    /* Erase 4KiB block on PMC chips */
 #define SPINOR_OP_BE_32K       0x52    /* Erase 32KiB block */
 #define SPINOR_OP_READ_1_2_2_4B        0xbc    /* Read data bytes (Dual I/O SPI) */
 #define SPINOR_OP_READ_1_1_4_4B        0x6c    /* Read data bytes (Quad Output SPI) */
 #define SPINOR_OP_READ_1_4_4_4B        0xec    /* Read data bytes (Quad I/O SPI) */
+#define SPINOR_OP_READ_1_1_8_4B        0x7c    /* Read data bytes (Octal Output SPI) */
+#define SPINOR_OP_READ_1_8_8_4B        0xcc    /* Read data bytes (Octal I/O SPI) */
 #define SPINOR_OP_PP_4B                0x12    /* Page program (up to 256 bytes) */
 #define SPINOR_OP_PP_1_1_4_4B  0x34    /* Quad page program */
 #define SPINOR_OP_PP_1_4_4_4B  0x3e    /* Quad page program */
+#define SPINOR_OP_PP_1_1_8_4B  0x84    /* Octal page program */
+#define SPINOR_OP_PP_1_8_8_4B  0x8e    /* Octal page program */
 #define SPINOR_OP_BE_4K_4B     0x21    /* Erase 4KiB block */
 #define SPINOR_OP_BE_32K_4B    0x5c    /* Erase 32KiB block */
 #define SPINOR_OP_SE_4B                0xdc    /* Sector erase (usually 64KiB) */
@@ -458,7 +466,7 @@ struct spi_nor_hwcaps {
 /*
  *(Fast) Read capabilities.
  * MUST be ordered by priority: the higher bit position, the higher priority.
- * As a matter of performances, it is relevant to use Octo SPI protocols first,
+ * As a matter of performances, it is relevant to use Octal SPI protocols first,
  * then Quad SPI protocols before Dual SPI protocols, Fast Read and lastly
  * (Slow) Read.
  */
@@ -479,7 +487,7 @@ struct spi_nor_hwcaps {
 #define SNOR_HWCAPS_READ_4_4_4         BIT(9)
 #define SNOR_HWCAPS_READ_1_4_4_DTR     BIT(10)
 
-#define SNOR_HWCPAS_READ_OCTO          GENMASK(14, 11)
+#define SNOR_HWCAPS_READ_OCTAL         GENMASK(14, 11)
 #define SNOR_HWCAPS_READ_1_1_8         BIT(11)
 #define SNOR_HWCAPS_READ_1_8_8         BIT(12)
 #define SNOR_HWCAPS_READ_8_8_8         BIT(13)
@@ -488,7 +496,7 @@ struct spi_nor_hwcaps {
 /*
  * Page Program capabilities.
  * MUST be ordered by priority: the higher bit position, the higher priority.
- * Like (Fast) Read capabilities, Octo/Quad SPI protocols are preferred to the
+ * Like (Fast) Read capabilities, Octal/Quad SPI protocols are preferred to the
  * legacy SPI 1-1-1 protocol.
  * Note that Dual Page Programs are not supported because there is no existing
  * JEDEC/SFDP standard to define them. Also at this moment no SPI flash memory
@@ -502,7 +510,7 @@ struct spi_nor_hwcaps {
 #define SNOR_HWCAPS_PP_1_4_4   BIT(18)
 #define SNOR_HWCAPS_PP_4_4_4   BIT(19)
 
-#define SNOR_HWCAPS_PP_OCT   GENMASK(22, 20)
+#define SNOR_HWCAPS_PP_OCTAL   GENMASK(22, 20)
 #define SNOR_HWCAPS_PP_1_1_8   BIT(20)
 #define SNOR_HWCAPS_PP_1_8_8   BIT(21)
 #define SNOR_HWCAPS_PP_8_8_8   BIT(22)