Merge tag 'spi-nor/for-5.5' into mtd/next
authorMiquel Raynal <miquel.raynal@bootlin.com>
Sun, 17 Nov 2019 17:34:01 +0000 (18:34 +0100)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Sun, 17 Nov 2019 17:34:01 +0000 (18:34 +0100)
SPI NOR core changes:
- introduce 'struct spi_nor_controller_ops',
- clean the Register Operations methods,
- use dev_dbg insted of dev_err for low level info,
- fix retlen handling in sst_write(),
- fix silent truncations in spi_nor_read and spi_nor_read_raw(),
- fix the clearing of QE bit on lock()/unlock(),
- rework the disabling of the block write protection,
- rework the Quad Enable methods,
- make sure nor->spimem and nor->controller_ops are mutually exclusive,
- set default Quad Enable method for ISSI flashes,
- add support for few flashes.

SPI NOR controller drivers changes:
- intel-spi:
- support chips without software sequencer,
- add support for Intel Cannon Lake and Intel Comet Lake-H flashes.

31 files changed:
Documentation/devicetree/bindings/mtd/intel,ixp4xx-flash.txt [new file with mode: 0644]
MAINTAINERS
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/cfi_cmdset_0020.c
drivers/mtd/chips/cfi_util.c
drivers/mtd/devices/mchp23k256.c
drivers/mtd/devices/spear_smi.c
drivers/mtd/devices/st_spi_fsm.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/l440gx.c
drivers/mtd/maps/physmap-core.c
drivers/mtd/maps/physmap-ixp4xx.c [new file with mode: 0644]
drivers/mtd/maps/physmap-ixp4xx.h [new file with mode: 0644]
drivers/mtd/mtdchar.c
drivers/mtd/mtdcore.c
drivers/mtd/mtdswap.c
drivers/mtd/nand/raw/denali_dt.c
drivers/mtd/nand/raw/hisi504_nand.c
drivers/mtd/nand/raw/lpc32xx_mlc.c
drivers/mtd/nand/raw/marvell_nand.c
drivers/mtd/nand/raw/meson_nand.c
drivers/mtd/nand/raw/mtk_ecc.c
drivers/mtd/nand/raw/mtk_nand.c
drivers/mtd/nand/raw/omap2.c
drivers/mtd/nand/raw/sh_flctl.c
drivers/mtd/nand/raw/stm32_fmc2_nand.c
drivers/mtd/nand/raw/sunxi_nand.c
drivers/mtd/spi-nor/cadence-quadspi.c
drivers/mtd/ubi/debug.c

diff --git a/Documentation/devicetree/bindings/mtd/intel,ixp4xx-flash.txt b/Documentation/devicetree/bindings/mtd/intel,ixp4xx-flash.txt
new file mode 100644 (file)
index 0000000..4bdcb92
--- /dev/null
@@ -0,0 +1,22 @@
+Flash device on Intel IXP4xx SoC
+
+This flash is regular CFI compatible (Intel or AMD extended) flash chips with
+specific big-endian or mixed-endian memory access pattern.
+
+Required properties:
+- compatible : must be "intel,ixp4xx-flash", "cfi-flash";
+- reg : memory address for the flash chip
+- bank-width : width in bytes of flash interface, should be <2>
+
+For the rest of the properties, see mtd-physmap.txt.
+
+The device tree may optionally contain sub-nodes describing partitions of the
+address space. See partition.txt for more detail.
+
+Example:
+
+flash@50000000 {
+       compatible = "intel,ixp4xx-flash", "cfi-flash";
+       reg = <0x50000000 0x01000000>;
+       bank-width = <2>;
+};
index e51a68b..306584f 100644 (file)
@@ -10529,15 +10529,13 @@ F:    include/linux/vmalloc.h
 F:     mm/
 
 MEMORY TECHNOLOGY DEVICES (MTD)
-M:     David Woodhouse <dwmw2@infradead.org>
-M:     Brian Norris <computersforpeace@gmail.com>
-M:     Marek Vasut <marek.vasut@gmail.com>
 M:     Miquel Raynal <miquel.raynal@bootlin.com>
 M:     Richard Weinberger <richard@nod.at>
 M:     Vignesh Raghavendra <vigneshr@ti.com>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
 Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
+C:     irc://irc.oftc.net/mtd
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/fixes
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
 S:     Maintained
@@ -15288,7 +15286,6 @@ F:      arch/arm/boot/dts/spear*
 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/
@@ -16585,10 +16582,9 @@ F:     drivers/media/pci/tw686x/
 
 UBI FILE SYSTEM (UBIFS)
 M:     Richard Weinberger <richard@nod.at>
-M:     Artem Bityutskiy <dedekind1@gmail.com>
-M:     Adrian Hunter <adrian.hunter@intel.com>
 L:     linux-mtd@lists.infradead.org
-T:     git git://git.infradead.org/ubifs-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git next
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git fixes
 W:     http://www.linux-mtd.infradead.org/doc/ubifs.html
 S:     Supported
 F:     Documentation/filesystems/ubifs.txt
@@ -16703,11 +16699,11 @@ S:    Maintained
 F:     drivers/scsi/ufs/ufs-mediatek*
 
 UNSORTED BLOCK IMAGES (UBI)
-M:     Artem Bityutskiy <dedekind1@gmail.com>
 M:     Richard Weinberger <richard@nod.at>
 W:     http://www.linux-mtd.infradead.org/
 L:     linux-mtd@lists.infradead.org
-T:     git git://git.infradead.org/ubifs-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git next
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git fixes
 S:     Supported
 F:     drivers/mtd/ubi/
 F:     include/linux/mtd/ubi.h
index 79a53cb..00a7948 100644 (file)
@@ -1353,7 +1353,7 @@ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t a
 {
        unsigned long cmd_addr;
        struct cfi_private *cfi = map->fldrv_priv;
-       int ret = 0;
+       int ret;
 
        adr += chip->start;
 
@@ -1383,7 +1383,7 @@ static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len,
        struct cfi_private *cfi = map->fldrv_priv;
        unsigned long ofs, last_end = 0;
        int chipnum;
-       int ret = 0;
+       int ret;
 
        if (!map->virt)
                return -EINVAL;
@@ -1550,7 +1550,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
 {
        struct cfi_private *cfi = map->fldrv_priv;
        map_word status, write_cmd;
-       int ret=0;
+       int ret;
 
        adr += chip->start;
 
@@ -1624,7 +1624,7 @@ static int cfi_intelext_write_words (struct mtd_info *mtd, loff_t to , size_t le
 {
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
-       int ret = 0;
+       int ret;
        int chipnum;
        unsigned long ofs;
 
@@ -1871,7 +1871,7 @@ static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
        int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
-       int ret = 0;
+       int ret;
        int chipnum;
        unsigned long ofs, vec_seek, i;
        size_t len = 0;
index cf8c8be..04b383b 100644 (file)
@@ -123,19 +123,23 @@ static int cfi_use_status_reg(struct cfi_private *cfi)
                (extp->SoftwareFeatures & poll_mask) == CFI_POLL_STATUS_REG;
 }
 
-static void cfi_check_err_status(struct map_info *map, struct flchip *chip,
-                                unsigned long adr)
+static int cfi_check_err_status(struct map_info *map, struct flchip *chip,
+                               unsigned long adr)
 {
        struct cfi_private *cfi = map->fldrv_priv;
        map_word status;
 
        if (!cfi_use_status_reg(cfi))
-               return;
+               return 0;
 
        cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
                         cfi->device_type, NULL);
        status = map_read(map, adr);
 
+       /* The error bits are invalid while the chip's busy */
+       if (!map_word_bitsset(map, status, CMD(CFI_SR_DRB)))
+               return 0;
+
        if (map_word_bitsset(map, status, CMD(0x3a))) {
                unsigned long chipstatus = MERGESTATUS(status);
 
@@ -151,7 +155,12 @@ static void cfi_check_err_status(struct map_info *map, struct flchip *chip,
                if (chipstatus & CFI_SR_SLSB)
                        pr_err("%s sector write protected, status %lx\n",
                               map->name, chipstatus);
+
+               /* Erase/Program status bits are set on the operation failure */
+               if (chipstatus & (CFI_SR_ESB | CFI_SR_PSB))
+                       return 1;
        }
+       return 0;
 }
 
 /* #define DEBUG_CFI_FEATURES */
@@ -785,7 +794,6 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
        kfree(mtd->eraseregions);
        kfree(mtd);
        kfree(cfi->cmdset_priv);
-       kfree(cfi->cfiq);
        return NULL;
 }
 
@@ -848,20 +856,16 @@ static int __xipram chip_good(struct map_info *map, struct flchip *chip,
 
        if (cfi_use_status_reg(cfi)) {
                map_word ready = CMD(CFI_SR_DRB);
-               map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB);
+
                /*
                 * For chips that support status register, check device
-                * ready bit and Erase/Program status bit to know if
-                * operation succeeded.
+                * ready bit
                 */
                cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
                                 cfi->device_type, NULL);
                curd = map_read(map, addr);
 
-               if (map_word_andequal(map, curd, ready, ready))
-                       return !map_word_bitsset(map, curd, err);
-
-               return 0;
+               return map_word_andequal(map, curd, ready, ready);
        }
 
        oldd = map_read(map, addr);
@@ -1699,8 +1703,11 @@ static int __xipram do_write_oneword_once(struct map_info *map,
                        break;
                }
 
-               if (chip_good(map, chip, adr, datum))
+               if (chip_good(map, chip, adr, datum)) {
+                       if (cfi_check_err_status(map, chip, adr))
+                               ret = -EIO;
                        break;
+               }
 
                /* Latency issues. Drop the lock, wait a while and retry */
                UDELAY(map, chip, adr, 1);
@@ -1713,7 +1720,7 @@ static int __xipram do_write_oneword_start(struct map_info *map,
                                           struct flchip *chip,
                                           unsigned long adr, int mode)
 {
-       int ret = 0;
+       int ret;
 
        mutex_lock(&chip->mutex);
 
@@ -1773,7 +1780,6 @@ static int __xipram do_write_oneword_retry(struct map_info *map,
        ret = do_write_oneword_once(map, chip, adr, datum, mode, cfi);
        if (ret) {
                /* reset on all failures. */
-               cfi_check_err_status(map, chip, adr);
                map_write(map, CMD(0xF0), chip->start);
                /* FIXME - should have reset delay before continuing */
 
@@ -1791,7 +1797,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
                                     unsigned long adr, map_word datum,
                                     int mode)
 {
-       int ret = 0;
+       int ret;
 
        adr += chip->start;
 
@@ -1815,7 +1821,7 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
 {
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
-       int ret = 0;
+       int ret;
        int chipnum;
        unsigned long ofs, chipstart;
        DECLARE_WAITQUEUE(wait, current);
@@ -1970,12 +1976,17 @@ static int __xipram do_write_buffer_wait(struct map_info *map,
                 */
                if (time_after(jiffies, timeo) &&
                    !chip_good(map, chip, adr, datum)) {
+                       pr_err("MTD %s(): software timeout, address:0x%.8lx.\n",
+                              __func__, adr);
                        ret = -EIO;
                        break;
                }
 
-               if (chip_good(map, chip, adr, datum))
+               if (chip_good(map, chip, adr, datum)) {
+                       if (cfi_check_err_status(map, chip, adr))
+                               ret = -EIO;
                        break;
+               }
 
                /* Latency issues. Drop the lock, wait a while and retry */
                UDELAY(map, chip, adr, 1);
@@ -2014,7 +2025,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
                                    int len)
 {
        struct cfi_private *cfi = map->fldrv_priv;
-       int ret = -EIO;
+       int ret;
        unsigned long cmd_adr;
        int z, words;
        map_word datum;
@@ -2071,12 +2082,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
                                chip->word_write_time);
 
        ret = do_write_buffer_wait(map, chip, adr, datum);
-       if (ret) {
-               cfi_check_err_status(map, chip, adr);
+       if (ret)
                do_write_buffer_reset(map, chip, cfi);
-               pr_err("MTD %s(): software timeout, address:0x%.8lx.\n",
-                      __func__, adr);
-       }
 
        xip_enable(map, chip, adr);
 
@@ -2095,7 +2102,7 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
        int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
-       int ret = 0;
+       int ret;
        int chipnum;
        unsigned long ofs;
 
@@ -2232,7 +2239,7 @@ static int do_panic_write_oneword(struct map_info *map, struct flchip *chip,
        struct cfi_private *cfi = map->fldrv_priv;
        int retry_cnt = 0;
        map_word oldd;
-       int ret = 0;
+       int ret;
        int i;
 
        adr += chip->start;
@@ -2271,9 +2278,9 @@ retry:
                udelay(1);
        }
 
-       if (!chip_good(map, chip, adr, datum)) {
+       if (!chip_good(map, chip, adr, datum) ||
+           cfi_check_err_status(map, chip, adr)) {
                /* reset on all failures. */
-               cfi_check_err_status(map, chip, adr);
                map_write(map, CMD(0xF0), chip->start);
                /* FIXME - should have reset delay before continuing */
 
@@ -2307,7 +2314,7 @@ static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
        unsigned long ofs, chipstart;
-       int ret = 0;
+       int ret;
        int chipnum;
 
        chipnum = to >> cfi->chipshift;
@@ -2411,7 +2418,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
        unsigned long timeo = jiffies + HZ;
        unsigned long int adr;
        DECLARE_WAITQUEUE(wait, current);
-       int ret = 0;
+       int ret;
        int retry_cnt = 0;
 
        adr = cfi->addr_unlock1;
@@ -2467,8 +2474,11 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
                        chip->erase_suspended = 0;
                }
 
-               if (chip_good(map, chip, adr, map_word_ff(map)))
+               if (chip_good(map, chip, adr, map_word_ff(map))) {
+                       if (cfi_check_err_status(map, chip, adr))
+                               ret = -EIO;
                        break;
+               }
 
                if (time_after(jiffies, timeo)) {
                        printk(KERN_WARNING "MTD %s(): software timeout\n",
@@ -2483,7 +2493,6 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
        /* Did we succeed? */
        if (ret) {
                /* reset on all failures. */
-               cfi_check_err_status(map, chip, adr);
                map_write(map, CMD(0xF0), chip->start);
                /* FIXME - should have reset delay before continuing */
 
@@ -2508,7 +2517,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
        struct cfi_private *cfi = map->fldrv_priv;
        unsigned long timeo = jiffies + HZ;
        DECLARE_WAITQUEUE(wait, current);
-       int ret = 0;
+       int ret;
        int retry_cnt = 0;
 
        adr += chip->start;
@@ -2564,8 +2573,11 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
                        chip->erase_suspended = 0;
                }
 
-               if (chip_good(map, chip, adr, map_word_ff(map)))
+               if (chip_good(map, chip, adr, map_word_ff(map))) {
+                       if (cfi_check_err_status(map, chip, adr))
+                               ret = -EIO;
                        break;
+               }
 
                if (time_after(jiffies, timeo)) {
                        printk(KERN_WARNING "MTD %s(): software timeout\n",
@@ -2580,7 +2592,6 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
        /* Did we succeed? */
        if (ret) {
                /* reset on all failures. */
-               cfi_check_err_status(map, chip, adr);
                map_write(map, CMD(0xF0), chip->start);
                /* FIXME - should have reset delay before continuing */
 
index e752067..54edae6 100644 (file)
@@ -611,7 +611,7 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
        int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
-       int ret = 0;
+       int ret;
        int chipnum;
        unsigned long ofs;
 
@@ -895,7 +895,7 @@ static int cfi_staa_erase_varsize(struct mtd_info *mtd,
 {      struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
        unsigned long adr, len;
-       int chipnum, ret = 0;
+       int chipnum, ret;
        int i, first;
        struct mtd_erase_region_info *regions = mtd->eraseregions;
 
@@ -1132,7 +1132,7 @@ static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
        unsigned long adr;
-       int chipnum, ret = 0;
+       int chipnum, ret;
 #ifdef DEBUG_LOCK_BITS
        int ofs_factor = cfi->interleave * cfi->device_type;
 #endif
@@ -1279,7 +1279,7 @@ static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
        unsigned long adr;
-       int chipnum, ret = 0;
+       int chipnum, ret;
 #ifdef DEBUG_LOCK_BITS
        int ofs_factor = cfi->interleave * cfi->device_type;
 #endif
index e3b266e..e2d4db0 100644 (file)
@@ -26,7 +26,7 @@
 void cfi_udelay(int us)
 {
        if (us >= 1000) {
-               msleep((us+999)/1000);
+               msleep(DIV_ROUND_UP(us, 1000));
        } else {
                udelay(us);
                cond_resched();
index b20d02b..77c872f 100644 (file)
@@ -64,15 +64,17 @@ static int mchp23k256_write(struct mtd_info *mtd, loff_t to, size_t len,
        struct spi_transfer transfer[2] = {};
        struct spi_message message;
        unsigned char command[MAX_CMD_SIZE];
-       int ret;
+       int ret, cmd_len;
 
        spi_message_init(&message);
 
+       cmd_len = mchp23k256_cmdsz(flash);
+
        command[0] = MCHP23K256_CMD_WRITE;
        mchp23k256_addr2cmd(flash, to, command);
 
        transfer[0].tx_buf = command;
-       transfer[0].len = mchp23k256_cmdsz(flash);
+       transfer[0].len = cmd_len;
        spi_message_add_tail(&transfer[0], &message);
 
        transfer[1].tx_buf = buf;
@@ -88,8 +90,8 @@ static int mchp23k256_write(struct mtd_info *mtd, loff_t to, size_t len,
        if (ret)
                return ret;
 
-       if (retlen && message.actual_length > sizeof(command))
-               *retlen += message.actual_length - sizeof(command);
+       if (retlen && message.actual_length > cmd_len)
+               *retlen += message.actual_length - cmd_len;
 
        return 0;
 }
@@ -101,16 +103,18 @@ static int mchp23k256_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct spi_transfer transfer[2] = {};
        struct spi_message message;
        unsigned char command[MAX_CMD_SIZE];
-       int ret;
+       int ret, cmd_len;
 
        spi_message_init(&message);
 
+       cmd_len = mchp23k256_cmdsz(flash);
+
        memset(&transfer, 0, sizeof(transfer));
        command[0] = MCHP23K256_CMD_READ;
        mchp23k256_addr2cmd(flash, from, command);
 
        transfer[0].tx_buf = command;
-       transfer[0].len = mchp23k256_cmdsz(flash);
+       transfer[0].len = cmd_len;
        spi_message_add_tail(&transfer[0], &message);
 
        transfer[1].rx_buf = buf;
@@ -126,8 +130,8 @@ static int mchp23k256_read(struct mtd_info *mtd, loff_t from, size_t len,
        if (ret)
                return ret;
 
-       if (retlen && message.actual_length > sizeof(command))
-               *retlen += message.actual_length - sizeof(command);
+       if (retlen && message.actual_length > cmd_len)
+               *retlen += message.actual_length - cmd_len;
 
        return 0;
 }
index 986f81d..79dcca1 100644 (file)
@@ -592,6 +592,26 @@ static int spear_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
        return 0;
 }
 
+/*
+ * The purpose of this function is to ensure a memcpy_toio() with byte writes
+ * only. Its structure is inspired from the ARM implementation of _memcpy_toio()
+ * which also does single byte writes but cannot be used here as this is just an
+ * implementation detail and not part of the API. Not mentioning the comment
+ * stating that _memcpy_toio() should be optimized.
+ */
+static void spear_smi_memcpy_toio_b(volatile void __iomem *dest,
+                                   const void *src, size_t len)
+{
+       const unsigned char *from = src;
+
+       while (len) {
+               len--;
+               writeb(*from, dest);
+               from++;
+               dest++;
+       }
+}
+
 static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank,
                void __iomem *dest, const void *src, size_t len)
 {
@@ -614,7 +634,23 @@ static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank,
        ctrlreg1 = readl(dev->io_base + SMI_CR1);
        writel((ctrlreg1 | WB_MODE) & ~SW_MODE, dev->io_base + SMI_CR1);
 
-       memcpy_toio(dest, src, len);
+       /*
+        * In Write Burst mode (WB_MODE), the specs states that writes must be:
+        * - incremental
+        * - of the same size
+        * The ARM implementation of memcpy_toio() will optimize the number of
+        * I/O by using as much 4-byte writes as possible, surrounded by
+        * 2-byte/1-byte access if:
+        * - the destination is not 4-byte aligned
+        * - the length is not a multiple of 4-byte.
+        * Avoid this alternance of write access size by using our own 'byte
+        * access' helper if at least one of the two conditions above is true.
+        */
+       if (IS_ALIGNED(len, sizeof(u32)) &&
+           IS_ALIGNED((uintptr_t)dest, sizeof(u32)))
+               memcpy_toio(dest, src, len);
+       else
+               spear_smi_memcpy_toio_b(dest, src, len);
 
        writel(ctrlreg1, dev->io_base + SMI_CR1);
 
@@ -777,9 +813,6 @@ static int spear_smi_probe_config_dt(struct platform_device *pdev,
 
        /* Fill structs for each subnode (flash device) */
        while ((pp = of_get_next_child(np, pp))) {
-               struct spear_smi_flash_info *flash_info;
-
-               flash_info = &pdata->board_flash_info[i];
                pdata->np[i] = pp;
 
                /* Read base-addr and size from DT */
@@ -933,7 +966,6 @@ static int spear_smi_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                ret = -ENODEV;
-               dev_err(&pdev->dev, "invalid smi irq\n");
                goto err;
        }
 
index f4d1667..1888523 100644 (file)
@@ -255,7 +255,6 @@ struct stfsm_seq {
 struct stfsm {
        struct device           *dev;
        void __iomem            *base;
-       struct resource         *region;
        struct mtd_info         mtd;
        struct mutex            lock;
        struct flash_info       *info;
index bc82305..b28225a 100644 (file)
@@ -96,6 +96,17 @@ config MTD_PHYSMAP_GEMINI
          platforms, some detection and setting up parallel mode on the
          external interface.
 
+config MTD_PHYSMAP_IXP4XX
+       bool "Intel IXP4xx OF-based physical memory map handling"
+       depends on MTD_PHYSMAP_OF
+       depends on ARM
+       select MTD_COMPLEX_MAPPINGS
+       select MTD_CFI_BE_BYTE_SWAP if CPU_BIG_ENDIAN
+       default ARCH_IXP4XX
+       help
+         This provides some extra DT physmap parsing for the Intel IXP4xx
+         platforms, some elaborate endianness handling in particular.
+
 config MTD_PHYSMAP_GPIO_ADDR
        bool "GPIO-assisted Flash Chip Support"
        depends on MTD_PHYSMAP
index 1146009..c0da86a 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_MTD_PXA2XX)      += pxa2xx-flash.o
 physmap-objs-y                 += physmap-core.o
 physmap-objs-$(CONFIG_MTD_PHYSMAP_VERSATILE) += physmap-versatile.o
 physmap-objs-$(CONFIG_MTD_PHYSMAP_GEMINI) += physmap-gemini.o
+physmap-objs-$(CONFIG_MTD_PHYSMAP_IXP4XX) += physmap-ixp4xx.o
 physmap-objs                   := $(physmap-objs-y)
 obj-$(CONFIG_MTD_PHYSMAP)      += physmap.o
 obj-$(CONFIG_MTD_PISMO)                += pismo.o
index 876f12f..0eeadfe 100644 (file)
@@ -86,7 +86,7 @@ static int __init init_l440gx(void)
                return -ENOMEM;
        }
        simple_map_init(&l440gx_map);
-       printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.virt);
+       pr_debug("window_addr = %p\n", l440gx_map.virt);
 
        /* Setup the pm iobase resource
         * This code should move into some kind of generic bridge
index 21b556a..a9f7964 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/gpio/consumer.h>
 
 #include "physmap-gemini.h"
+#include "physmap-ixp4xx.h"
 #include "physmap-versatile.h"
 
 struct physmap_flash_info {
@@ -370,6 +371,10 @@ static int physmap_flash_of_init(struct platform_device *dev)
                if (err)
                        return err;
 
+               err = of_flash_probe_ixp4xx(dev, dp, &info->maps[i]);
+               if (err)
+                       return err;
+
                err = of_flash_probe_versatile(dev, dp, &info->maps[i]);
                if (err)
                        return err;
diff --git a/drivers/mtd/maps/physmap-ixp4xx.c b/drivers/mtd/maps/physmap-ixp4xx.c
new file mode 100644 (file)
index 0000000..6a05422
--- /dev/null
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel IXP4xx OF physmap add-on
+ * Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
+ *
+ * Based on the ixp4xx.c map driver, originally written by:
+ * Intel Corporation
+ * Deepak Saxena <dsaxena@mvista.com>
+ * Copyright (C) 2002 Intel Corporation
+ * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ */
+#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/xip.h>
+#include "physmap-ixp4xx.h"
+
+/*
+ * Read/write a 16 bit word from flash address 'addr'.
+ *
+ * When the cpu is in little-endian mode it swizzles the address lines
+ * ('address coherency') so we need to undo the swizzling to ensure commands
+ * and the like end up on the correct flash address.
+ *
+ * To further complicate matters, due to the way the expansion bus controller
+ * handles 32 bit reads, the byte stream ABCD is stored on the flash as:
+ *     D15    D0
+ *     +---+---+
+ *     | A | B | 0
+ *     +---+---+
+ *     | C | D | 2
+ *     +---+---+
+ * This means that on LE systems each 16 bit word must be swapped. Note that
+ * this requires CONFIG_MTD_CFI_BE_BYTE_SWAP to be enabled to 'unswap' the CFI
+ * data and other flash commands which are always in D7-D0.
+ */
+#ifndef CONFIG_CPU_BIG_ENDIAN
+
+static inline u16 flash_read16(void __iomem *addr)
+{
+       return be16_to_cpu(__raw_readw((void __iomem *)((unsigned long)addr ^ 0x2)));
+}
+
+static inline void flash_write16(u16 d, void __iomem *addr)
+{
+       __raw_writew(cpu_to_be16(d), (void __iomem *)((unsigned long)addr ^ 0x2));
+}
+
+#define        BYTE0(h)        ((h) & 0xFF)
+#define        BYTE1(h)        (((h) >> 8) & 0xFF)
+
+#else
+
+static inline u16 flash_read16(const void __iomem *addr)
+{
+       return __raw_readw(addr);
+}
+
+static inline void flash_write16(u16 d, void __iomem *addr)
+{
+       __raw_writew(d, addr);
+}
+
+#define        BYTE0(h)        (((h) >> 8) & 0xFF)
+#define        BYTE1(h)        ((h) & 0xFF)
+#endif
+
+static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
+{
+       map_word val;
+
+       val.x[0] = flash_read16(map->virt + ofs);
+       return val;
+}
+
+/*
+ * The IXP4xx expansion bus only allows 16-bit wide acceses
+ * when attached to a 16-bit wide device (such as the 28F128J3A),
+ * so we can't just memcpy_fromio().
+ */
+static void ixp4xx_copy_from(struct map_info *map, void *to,
+                            unsigned long from, ssize_t len)
+{
+       u8 *dest = (u8 *) to;
+       void __iomem *src = map->virt + from;
+
+       if (len <= 0)
+               return;
+
+       if (from & 1) {
+               *dest++ = BYTE1(flash_read16(src-1));
+               src++;
+               --len;
+       }
+
+       while (len >= 2) {
+               u16 data = flash_read16(src);
+               *dest++ = BYTE0(data);
+               *dest++ = BYTE1(data);
+               src += 2;
+               len -= 2;
+       }
+
+       if (len > 0)
+               *dest++ = BYTE0(flash_read16(src));
+}
+
+static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
+{
+       flash_write16(d.x[0], map->virt + adr);
+}
+
+int of_flash_probe_ixp4xx(struct platform_device *pdev,
+                         struct device_node *np,
+                         struct map_info *map)
+{
+       struct device *dev = &pdev->dev;
+
+       /* Multiplatform guard */
+       if (!of_device_is_compatible(np, "intel,ixp4xx-flash"))
+               return 0;
+
+       map->read = ixp4xx_read16;
+       map->write = ixp4xx_write16;
+       map->copy_from = ixp4xx_copy_from;
+       map->copy_to = NULL;
+
+       dev_info(dev, "initialized Intel IXP4xx-specific physmap control\n");
+
+       return 0;
+}
diff --git a/drivers/mtd/maps/physmap-ixp4xx.h b/drivers/mtd/maps/physmap-ixp4xx.h
new file mode 100644 (file)
index 0000000..b0fc49b
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/of.h>
+#include <linux/mtd/map.h>
+
+#ifdef CONFIG_MTD_PHYSMAP_IXP4XX
+int of_flash_probe_ixp4xx(struct platform_device *pdev,
+                         struct device_node *np,
+                         struct map_info *map);
+#else
+static inline
+int of_flash_probe_ixp4xx(struct platform_device *pdev,
+                         struct device_node *np,
+                         struct map_info *map)
+{
+       return 0;
+}
+#endif
index 975aed9..b841008 100644 (file)
@@ -174,7 +174,7 @@ static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count,
                        break;
                case MTD_FILE_MODE_RAW:
                {
-                       struct mtd_oob_ops ops;
+                       struct mtd_oob_ops ops = {};
 
                        ops.mode = MTD_OPS_RAW;
                        ops.datbuf = kbuf;
@@ -268,7 +268,7 @@ static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t c
 
                case MTD_FILE_MODE_RAW:
                {
-                       struct mtd_oob_ops ops;
+                       struct mtd_oob_ops ops = {};
 
                        ops.mode = MTD_OPS_RAW;
                        ops.datbuf = kbuf;
@@ -350,7 +350,7 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd,
        uint32_t __user *retp)
 {
        struct mtd_file_info *mfi = file->private_data;
-       struct mtd_oob_ops ops;
+       struct mtd_oob_ops ops = {};
        uint32_t retlen;
        int ret = 0;
 
@@ -394,7 +394,7 @@ static int mtdchar_readoob(struct file *file, struct mtd_info *mtd,
        uint32_t __user *retp)
 {
        struct mtd_file_info *mfi = file->private_data;
-       struct mtd_oob_ops ops;
+       struct mtd_oob_ops ops = {};
        int ret = 0;
 
        if (length > 4096)
@@ -587,7 +587,7 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd,
                struct mtd_write_req __user *argp)
 {
        struct mtd_write_req req;
-       struct mtd_oob_ops ops;
+       struct mtd_oob_ops ops = {};
        const void __user *usr_data, *usr_oob;
        int ret;
 
index 6cc7ecb..5fac435 100644 (file)
@@ -382,33 +382,21 @@ static struct dentry *dfs_dir_mtd;
 static void mtd_debugfs_populate(struct mtd_info *mtd)
 {
        struct device *dev = &mtd->dev;
-       struct dentry *root, *dent;
+       struct dentry *root;
 
        if (IS_ERR_OR_NULL(dfs_dir_mtd))
                return;
 
        root = debugfs_create_dir(dev_name(dev), dfs_dir_mtd);
-       if (IS_ERR_OR_NULL(root)) {
-               dev_dbg(dev, "won't show data in debugfs\n");
-               return;
-       }
-
        mtd->dbg.dfs_dir = root;
 
-       if (mtd->dbg.partid) {
-               dent = debugfs_create_file("partid", 0400, root, mtd,
-                                          &mtd_partid_debug_fops);
-               if (IS_ERR_OR_NULL(dent))
-                       dev_err(dev, "can't create debugfs entry for partid\n");
-       }
+       if (mtd->dbg.partid)
+               debugfs_create_file("partid", 0400, root, mtd,
+                                   &mtd_partid_debug_fops);
 
-       if (mtd->dbg.partname) {
-               dent = debugfs_create_file("partname", 0400, root, mtd,
-                                          &mtd_partname_debug_fops);
-               if (IS_ERR_OR_NULL(dent))
-                       dev_err(dev,
-                               "can't create debugfs entry for partname\n");
-       }
+       if (mtd->dbg.partname)
+               debugfs_create_file("partname", 0400, root, mtd,
+                                   &mtd_partname_debug_fops);
 }
 
 #ifndef CONFIG_MMU
index f92414e..58eefa4 100644 (file)
@@ -1257,7 +1257,6 @@ DEFINE_SHOW_ATTRIBUTE(mtdswap);
 static int mtdswap_add_debugfs(struct mtdswap_dev *d)
 {
        struct dentry *root = d->mtd->dbg.dfs_dir;
-       struct dentry *dent;
 
        if (!IS_ENABLED(CONFIG_DEBUG_FS))
                return 0;
@@ -1265,12 +1264,7 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d)
        if (IS_ERR_OR_NULL(root))
                return -1;
 
-       dent = debugfs_create_file("mtdswap_stats", S_IRUSR, root, d,
-                               &mtdswap_fops);
-       if (!dent) {
-               dev_err(d->dev, "debugfs_create_file failed\n");
-               return -1;
-       }
+       debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops);
 
        return 0;
 }
index 5e14836..df99255 100644 (file)
@@ -167,10 +167,8 @@ static int denali_dt_probe(struct platform_device *pdev)
 
        denali->dev = dev;
        denali->irq = platform_get_irq(pdev, 0);
-       if (denali->irq < 0) {
-               dev_err(dev, "no irq defined\n");
+       if (denali->irq < 0)
                return denali->irq;
-       }
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "denali_reg");
        denali->reg = devm_ioremap_resource(dev, res);
index 6a4626a..0b48be5 100644 (file)
@@ -751,10 +751,8 @@ static int hisi_nfc_probe(struct platform_device *pdev)
        mtd  = nand_to_mtd(chip);
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(dev, "no IRQ resource defined\n");
+       if (irq < 0)
                return -ENXIO;
-       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        host->iobase = devm_ioremap_resource(dev, res);
index 78b31f8..241b58b 100644 (file)
@@ -773,7 +773,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 
        host->irq = platform_get_irq(pdev, 0);
        if (host->irq < 0) {
-               dev_err(&pdev->dev, "failed to get platform irq\n");
                res = -EINVAL;
                goto release_dma_chan;
        }
index fc49e13..fb5abdc 100644 (file)
@@ -2862,10 +2862,8 @@ static int marvell_nfc_probe(struct platform_device *pdev)
                return PTR_ERR(nfc->regs);
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(dev, "failed to retrieve irq\n");
+       if (irq < 0)
                return irq;
-       }
 
        nfc->core_clk = devm_clk_get(&pdev->dev, "core");
 
index 1b82b68..9f17b5b 100644 (file)
@@ -1399,10 +1399,8 @@ static int meson_nfc_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(dev, "no NFC IRQ resource\n");
+       if (irq < 0)
                return -EINVAL;
-       }
 
        ret = meson_nfc_clk_init(nfc);
        if (ret) {
index 74595b6..75f1fa3 100644 (file)
@@ -527,10 +527,8 @@ static int mtk_ecc_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(dev, "failed to get irq: %d\n", irq);
+       if (irq < 0)
                return irq;
-       }
 
        ret = dma_set_mask(dev, DMA_BIT_MASK(32));
        if (ret) {
index 373d47d..b8305e3 100644 (file)
@@ -1540,7 +1540,6 @@ static int mtk_nfc_probe(struct platform_device *pdev)
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
-               dev_err(dev, "no nfi irq resource\n");
                ret = -EINVAL;
                goto clk_disable;
        }
index 6ec65f4..ad77c11 100644 (file)
@@ -1967,10 +1967,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
 
        case NAND_OMAP_PREFETCH_IRQ:
                info->gpmc_irq_fifo = platform_get_irq(info->pdev, 0);
-               if (info->gpmc_irq_fifo <= 0) {
-                       dev_err(dev, "Error getting fifo IRQ\n");
+               if (info->gpmc_irq_fifo <= 0)
                        return -ENODEV;
-               }
                err = devm_request_irq(dev, info->gpmc_irq_fifo,
                                       omap_nand_irq, IRQF_SHARED,
                                       "gpmc-nand-fifo", info);
@@ -1982,10 +1980,8 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
                }
 
                info->gpmc_irq_count = platform_get_irq(info->pdev, 1);
-               if (info->gpmc_irq_count <= 0) {
-                       dev_err(dev, "Error getting IRQ count\n");
+               if (info->gpmc_irq_count <= 0)
                        return -ENODEV;
-               }
                err = devm_request_irq(dev, info->gpmc_irq_count,
                                       omap_nand_irq, IRQF_SHARED,
                                       "gpmc-nand-count", info);
index e509c93..058e99d 100644 (file)
@@ -1129,10 +1129,8 @@ static int flctl_probe(struct platform_device *pdev)
        flctl->fifo = res->start + 0x24; /* FLDTFIFO */
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "failed to get flste irq data: %d\n", irq);
+       if (irq < 0)
                return irq;
-       }
 
        ret = devm_request_irq(&pdev->dev, irq, flctl_handle_flste, IRQF_SHARED,
                               "flste", flctl);
index 8cc852d..9e63800 100644 (file)
@@ -1880,11 +1880,8 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               if (irq != -EPROBE_DEFER)
-                       dev_err(dev, "IRQ error missing or invalid\n");
+       if (irq < 0)
                return irq;
-       }
 
        ret = devm_request_irq(dev, irq, stm32_fmc2_irq, 0,
                               dev_name(dev), fmc2);
index 8977329..37a4ac0 100644 (file)
@@ -2071,10 +2071,8 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
                return PTR_ERR(nfc->regs);
 
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(dev, "failed to retrieve irq\n");
+       if (irq < 0)
                return irq;
-       }
 
        nfc->ahb_clk = devm_clk_get(dev, "ahb");
        if (IS_ERR(nfc->ahb_clk)) {
index 22008fe..06f9972 100644 (file)
@@ -1370,10 +1370,8 @@ static int cqspi_probe(struct platform_device *pdev)
 
        /* Obtain IRQ line. */
        irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(dev, "Cannot obtain IRQ.\n");
+       if (irq < 0)
                return -ENXIO;
-       }
 
        pm_runtime_enable(dev);
        ret = pm_runtime_get_sync(dev);
index a1dff92..0f847d5 100644 (file)
@@ -509,11 +509,9 @@ static const struct file_operations eraseblk_count_fops = {
  */
 int ubi_debugfs_init_dev(struct ubi_device *ubi)
 {
-       int err, n;
        unsigned long ubi_num = ubi->ubi_num;
-       const char *fname;
-       struct dentry *dent;
        struct ubi_debug_info *d = &ubi->dbg;
+       int n;
 
        if (!IS_ENABLED(CONFIG_DEBUG_FS))
                return 0;
@@ -522,95 +520,52 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
                     ubi->ubi_num);
        if (n == UBI_DFS_DIR_LEN) {
                /* The array size is too small */
-               fname = UBI_DFS_DIR_NAME;
-               dent = ERR_PTR(-EINVAL);
-               goto out;
+               return -EINVAL;
        }
 
-       fname = d->dfs_dir_name;
-       dent = debugfs_create_dir(fname, dfs_rootdir);
-       if (IS_ERR_OR_NULL(dent))
-               goto out;
-       d->dfs_dir = dent;
-
-       fname = "chk_gen";
-       dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
-                                  &dfs_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
-       d->dfs_chk_gen = dent;
-
-       fname = "chk_io";
-       dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
-                                  &dfs_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
-       d->dfs_chk_io = dent;
-
-       fname = "chk_fastmap";
-       dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
-                                  &dfs_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
-       d->dfs_chk_fastmap = dent;
-
-       fname = "tst_disable_bgt";
-       dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
-                                  &dfs_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
-       d->dfs_disable_bgt = dent;
-
-       fname = "tst_emulate_bitflips";
-       dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
-                                  &dfs_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
-       d->dfs_emulate_bitflips = dent;
-
-       fname = "tst_emulate_io_failures";
-       dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
-                                  &dfs_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
-       d->dfs_emulate_io_failures = dent;
-
-       fname = "tst_emulate_power_cut";
-       dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
-                                  &dfs_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
-       d->dfs_emulate_power_cut = dent;
-
-       fname = "tst_emulate_power_cut_min";
-       dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
-                                  &dfs_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
-       d->dfs_power_cut_min = dent;
-
-       fname = "tst_emulate_power_cut_max";
-       dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
-                                  &dfs_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
-       d->dfs_power_cut_max = dent;
-
-       fname = "detailed_erase_block_info";
-       dent = debugfs_create_file(fname, S_IRUSR, d->dfs_dir, (void *)ubi_num,
-                                  &eraseblk_count_fops);
-       if (IS_ERR_OR_NULL(dent))
-               goto out_remove;
+       d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir);
 
-       return 0;
+       d->dfs_chk_gen = debugfs_create_file("chk_gen", S_IWUSR, d->dfs_dir,
+                                            (void *)ubi_num, &dfs_fops);
 
-out_remove:
-       debugfs_remove_recursive(d->dfs_dir);
-out:
-       err = dent ? PTR_ERR(dent) : -ENODEV;
-       ubi_err(ubi, "cannot create \"%s\" debugfs file or directory, error %d\n",
-               fname, err);
-       return err;
+       d->dfs_chk_io = debugfs_create_file("chk_io", S_IWUSR, d->dfs_dir,
+                                           (void *)ubi_num, &dfs_fops);
+
+       d->dfs_chk_fastmap = debugfs_create_file("chk_fastmap", S_IWUSR,
+                                                d->dfs_dir, (void *)ubi_num,
+                                                &dfs_fops);
+
+       d->dfs_disable_bgt = debugfs_create_file("tst_disable_bgt", S_IWUSR,
+                                                d->dfs_dir, (void *)ubi_num,
+                                                &dfs_fops);
+
+       d->dfs_emulate_bitflips = debugfs_create_file("tst_emulate_bitflips",
+                                                     S_IWUSR, d->dfs_dir,
+                                                     (void *)ubi_num,
+                                                     &dfs_fops);
+
+       d->dfs_emulate_io_failures = debugfs_create_file("tst_emulate_io_failures",
+                                                        S_IWUSR, d->dfs_dir,
+                                                        (void *)ubi_num,
+                                                        &dfs_fops);
+
+       d->dfs_emulate_power_cut = debugfs_create_file("tst_emulate_power_cut",
+                                                      S_IWUSR, d->dfs_dir,
+                                                      (void *)ubi_num,
+                                                      &dfs_fops);
+
+       d->dfs_power_cut_min = debugfs_create_file("tst_emulate_power_cut_min",
+                                                  S_IWUSR, d->dfs_dir,
+                                                  (void *)ubi_num, &dfs_fops);
+
+       d->dfs_power_cut_max = debugfs_create_file("tst_emulate_power_cut_max",
+                                                  S_IWUSR, d->dfs_dir,
+                                                  (void *)ubi_num, &dfs_fops);
+
+       debugfs_create_file("detailed_erase_block_info", S_IRUSR, d->dfs_dir,
+                           (void *)ubi_num, &eraseblk_count_fops);
+
+       return 0;
 }
 
 /**