Merge tag 'for-linus-20161104' of git://git.infradead.org/linux-mtd
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 5 Nov 2016 17:52:29 +0000 (10:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 5 Nov 2016 17:52:29 +0000 (10:52 -0700)
Pull MTD fixes from Brian Norris:

 - MAINTAINERS updates to reflect some new maintainers/submaintainers.

   We have some great volunteers who've been developing and reviewing
   already. We're going to try a group maintainership model, so
   eventually you'll probably see pull requests from people besides me.

 - NAND fixes from Boris:
    "Three simple fixes:

      - fix a non-critical bug in the gpmi driver
      - fix a bug in the 'automatic NAND timings selection' feature
        introduced in 4.9-rc1
      - fix a false positive uninitialized-var warning"

* tag 'for-linus-20161104' of git://git.infradead.org/linux-mtd:
  mtd: mtk: avoid warning in mtk_ecc_encode
  mtd: nand: Fix data interface configuration logic
  mtd: nand: gpmi: disable the clocks on errors
  MAINTAINERS: add more people to the MTD maintainer team
  MAINTAINERS: add a maintainer for the SPI NOR subsystem

MAINTAINERS
drivers/mtd/nand/gpmi-nand/gpmi-lib.c
drivers/mtd/nand/mtk_ecc.c
drivers/mtd/nand/nand_base.c
include/linux/mtd/nand.h

index ccae35b..411e3b8 100644 (file)
@@ -7925,6 +7925,10 @@ F:       mm/
 MEMORY TECHNOLOGY DEVICES (MTD)
 M:     David Woodhouse <dwmw2@infradead.org>
 M:     Brian Norris <computersforpeace@gmail.com>
+M:     Boris Brezillon <boris.brezillon@free-electrons.com>
+M:     Marek Vasut <marek.vasut@gmail.com>
+M:     Richard Weinberger <richard@nod.at>
+M:     Cyrille Pitchen <cyrille.pitchen@atmel.com>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
 Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
@@ -11404,6 +11408,17 @@ W:     http://www.st.com/spear
 S:     Maintained
 F:     drivers/clk/spear/
 
+SPI NOR SUBSYSTEM
+M:     Cyrille Pitchen <cyrille.pitchen@atmel.com>
+M:     Marek Vasut <marek.vasut@gmail.com>
+L:     linux-mtd@lists.infradead.org
+W:     http://www.linux-mtd.infradead.org/
+Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
+T:     git git://github.com/spi-nor/linux.git
+S:     Maintained
+F:     drivers/mtd/spi-nor/
+F:     include/linux/mtd/spi-nor.h
+
 SPI SUBSYSTEM
 M:     Mark Brown <broonie@kernel.org>
 L:     linux-spi@vger.kernel.org
index 0f68a99..141bd70 100644 (file)
@@ -161,7 +161,7 @@ int gpmi_init(struct gpmi_nand_data *this)
 
        ret = gpmi_enable_clk(this);
        if (ret)
-               goto err_out;
+               return ret;
        ret = gpmi_reset_block(r->gpmi_regs, false);
        if (ret)
                goto err_out;
@@ -197,6 +197,7 @@ int gpmi_init(struct gpmi_nand_data *this)
        gpmi_disable_clk(this);
        return 0;
 err_out:
+       gpmi_disable_clk(this);
        return ret;
 }
 
@@ -270,7 +271,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)
 
        ret = gpmi_enable_clk(this);
        if (ret)
-               goto err_out;
+               return ret;
 
        /*
        * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
@@ -308,6 +309,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        gpmi_disable_clk(this);
        return 0;
 err_out:
+       gpmi_disable_clk(this);
        return ret;
 }
 
index d54f666..dbf2562 100644 (file)
@@ -86,6 +86,8 @@ struct mtk_ecc {
        struct completion done;
        struct mutex lock;
        u32 sectors;
+
+       u8 eccdata[112];
 };
 
 static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
@@ -366,9 +368,8 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,
                   u8 *data, u32 bytes)
 {
        dma_addr_t addr;
-       u8 *p;
-       u32 len, i, val;
-       int ret = 0;
+       u32 len;
+       int ret;
 
        addr = dma_map_single(ecc->dev, data, bytes, DMA_TO_DEVICE);
        ret = dma_mapping_error(ecc->dev, addr);
@@ -393,14 +394,12 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,
 
        /* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */
        len = (config->strength * ECC_PARITY_BITS + 7) >> 3;
-       p = data + bytes;
 
-       /* write the parity bytes generated by the ECC back to the OOB region */
-       for (i = 0; i < len; i++) {
-               if ((i % 4) == 0)
-                       val = readl(ecc->regs + ECC_ENCPAR(i / 4));
-               p[i] = (val >> ((i % 4) * 8)) & 0xff;
-       }
+       /* write the parity bytes generated by the ECC back to temp buffer */
+       __ioread32_copy(ecc->eccdata, ecc->regs + ECC_ENCPAR(0), round_up(len, 4));
+
+       /* copy into possibly unaligned OOB region with actual length */
+       memcpy(data + bytes, ecc->eccdata, len);
 timeout:
 
        dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE);
index e5718e5..3bde96a 100644 (file)
@@ -1095,10 +1095,11 @@ static void nand_release_data_interface(struct nand_chip *chip)
 /**
  * nand_reset - Reset and initialize a NAND device
  * @chip: The NAND chip
+ * @chipnr: Internal die id
  *
  * Returns 0 for success or negative error code otherwise
  */
-int nand_reset(struct nand_chip *chip)
+int nand_reset(struct nand_chip *chip, int chipnr)
 {
        struct mtd_info *mtd = nand_to_mtd(chip);
        int ret;
@@ -1107,9 +1108,17 @@ int nand_reset(struct nand_chip *chip)
        if (ret)
                return ret;
 
+       /*
+        * The CS line has to be released before we can apply the new NAND
+        * interface settings, hence this weird ->select_chip() dance.
+        */
+       chip->select_chip(mtd, chipnr);
        chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+       chip->select_chip(mtd, -1);
 
+       chip->select_chip(mtd, chipnr);
        ret = nand_setup_data_interface(chip);
+       chip->select_chip(mtd, -1);
        if (ret)
                return ret;
 
@@ -1185,8 +1194,6 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
        /* Shift to get chip number */
        chipnr = ofs >> chip->chip_shift;
 
-       chip->select_chip(mtd, chipnr);
-
        /*
         * Reset the chip.
         * If we want to check the WP through READ STATUS and check the bit 7
@@ -1194,7 +1201,9 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
         * some operation can also clear the bit 7 of status register
         * eg. erase/program a locked block
         */
-       nand_reset(chip);
+       nand_reset(chip, chipnr);
+
+       chip->select_chip(mtd, chipnr);
 
        /* Check, if it is write protected */
        if (nand_check_wp(mtd)) {
@@ -1244,8 +1253,6 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
        /* Shift to get chip number */
        chipnr = ofs >> chip->chip_shift;
 
-       chip->select_chip(mtd, chipnr);
-
        /*
         * Reset the chip.
         * If we want to check the WP through READ STATUS and check the bit 7
@@ -1253,7 +1260,9 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
         * some operation can also clear the bit 7 of status register
         * eg. erase/program a locked block
         */
-       nand_reset(chip);
+       nand_reset(chip, chipnr);
+
+       chip->select_chip(mtd, chipnr);
 
        /* Check, if it is write protected */
        if (nand_check_wp(mtd)) {
@@ -2940,10 +2949,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
        }
 
        chipnr = (int)(to >> chip->chip_shift);
-       chip->select_chip(mtd, chipnr);
-
-       /* Shift to get page */
-       page = (int)(to >> chip->page_shift);
 
        /*
         * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
@@ -2951,7 +2956,12 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
         * if we don't do this. I have no clue why, but I seem to have 'fixed'
         * it in the doc2000 driver in August 1999.  dwmw2.
         */
-       nand_reset(chip);
+       nand_reset(chip, chipnr);
+
+       chip->select_chip(mtd, chipnr);
+
+       /* Shift to get page */
+       page = (int)(to >> chip->page_shift);
 
        /* Check, if it is write protected */
        if (nand_check_wp(mtd)) {
@@ -3984,14 +3994,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
        int i, maf_idx;
        u8 id_data[8];
 
-       /* Select the device */
-       chip->select_chip(mtd, 0);
-
        /*
         * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
         * after power-up.
         */
-       nand_reset(chip);
+       nand_reset(chip, 0);
+
+       /* Select the device */
+       chip->select_chip(mtd, 0);
 
        /* Send the command for reading device ID */
        chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
@@ -4329,17 +4339,31 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
                return PTR_ERR(type);
        }
 
+       /* Initialize the ->data_interface field. */
        ret = nand_init_data_interface(chip);
        if (ret)
                return ret;
 
+       /*
+        * Setup the data interface correctly on the chip and controller side.
+        * This explicit call to nand_setup_data_interface() is only required
+        * for the first die, because nand_reset() has been called before
+        * ->data_interface and ->default_onfi_timing_mode were set.
+        * For the other dies, nand_reset() will automatically switch to the
+        * best mode for us.
+        */
+       ret = nand_setup_data_interface(chip);
+       if (ret)
+               return ret;
+
        chip->select_chip(mtd, -1);
 
        /* Check for a chip array */
        for (i = 1; i < maxchips; i++) {
-               chip->select_chip(mtd, i);
                /* See comment in nand_get_flash_type for reset */
-               nand_reset(chip);
+               nand_reset(chip, i);
+
+               chip->select_chip(mtd, i);
                /* Send the command for reading device ID */
                chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
                /* Read manufacturer and device IDs */
index c5d3d50..d8905a2 100644 (file)
@@ -1184,7 +1184,7 @@ int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
                           int page);
 
 /* Reset and initialize a NAND device */
-int nand_reset(struct nand_chip *chip);
+int nand_reset(struct nand_chip *chip, int chipnr);
 
 /* Free resources held by the NAND device */
 void nand_cleanup(struct nand_chip *chip);