diff --git a/ChangeLog b/ChangeLog
index 9c7be4e864940a9f7071c690f76c49902ad76080..4dbe42cd166a22678f8b61b95c9faa133ac96647 100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -11152,4 +11152,10 @@
 	* drivers/lcd/ili9432.c:  Fixed errors in orientation. Portrait,
 	  RPortrait, and RLandscript should work correly now.  They were
 	  displayed mirrored.  From  Marco Krahl (2015-11-25).
-
+	* drivers/mtd/mtd/mtd_procfs/c and include/nuttx/mtd/mtd.h:  Add an
+	  interface to un-regiser an MTD procfs entry.  From Ken Petit
+	  (2015-11-25).
+	* drivers/mtd/filemtd.c:  New new MTD conversion layer that will
+	  convert a regular file (or driver file) to an MTD device.  This is
+	  useful for testing on the simulation using the hostfs.  From Ken
+	  Petit (2015-11-25).
diff --git a/drivers/mtd/filemtd.c b/drivers/mtd/filemtd.c
new file mode 100644
index 0000000000000000000000000000000000000000..ba24f4a02384019cb9eb057c62af8b999d41adca
--- /dev/null
+++ b/drivers/mtd/filemtd.c
@@ -0,0 +1,590 @@
+/****************************************************************************
+ * drivers/mtd/filemtd.c
+ *
+ *   Copyright (C) 2015 Ken Pettit. All rights reserved.
+ *   Author: Ken Pettit <pettitkd@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/mtd/mtd.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_FILEMTD_BLOCKSIZE
+#  define CONFIG_FILEMTD_BLOCKSIZE 512
+#endif
+
+#ifndef CONFIG_FILEMTD_ERASESIZE
+#  define CONFIG_FILEMTD_ERASESIZE 4096
+#endif
+
+#ifndef CONFIG_FILEMTD_ERASESTATE
+#  define CONFIG_FILEMTD_ERASESTATE 0xff
+#endif
+
+#if CONFIG_FILEMTD_ERASESTATE != 0xff && CONFIG_FILEMTD_ERASESTATE != 0x00
+#  error "Unsupported value for CONFIG_FILEMTD_ERASESTATE"
+#endif
+
+#if CONFIG_FILEMTD_BLOCKSIZE > CONFIG_FILEMTD_ERASESIZE
+#  error "Must have CONFIG_FILEMTD_BLOCKSIZE <= CONFIG_FILEMTD_ERASESIZE"
+#endif
+
+#undef  FILEMTD_BLKPER
+#define FILEMTD_BLKPER (CONFIG_FILEMTD_ERASESIZE/CONFIG_FILEMTD_BLOCKSIZE)
+
+#if FILEMTD_BLKPER*CONFIG_FILEMTD_BLOCKSIZE != CONFIG_FILEMTD_ERASESIZE
+#  error "CONFIG_FILEMTD_ERASESIZE must be an even multiple of CONFIG_FILEMTD_BLOCKSIZE"
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This type represents the state of the MTD device.  The struct mtd_dev_s
+ * must appear at the beginning of the definition so that you can freely
+ * cast between pointers to struct mtd_dev_s and struct file_dev_s.
+ */
+
+struct file_dev_s
+{
+  struct mtd_dev_s mtd;      /* MTD device */
+  int              fd;       /* File descriptor of underlying file */
+  size_t           nblocks;  /* Number of erase blocks */
+  size_t           offset;   /* Offset from start of file */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static ssize_t filemtd_read(FAR struct file_dev_s *priv, unsigned char *buffer,
+                 size_t offsetbytes, unsigned int nbytes);
+static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset, FAR const void *src, size_t len);
+
+/* MTD driver methods */
+
+static int file_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
+static ssize_t file_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
+                          FAR uint8_t *buf);
+static ssize_t file_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
+                           FAR const uint8_t *buf);
+static ssize_t file_byteread(FAR struct mtd_dev_s *dev, off_t offset,
+                            size_t nbytes, FAR uint8_t *buf);
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t file_bytewrite(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR const uint8_t *buf);
+#endif
+static int file_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: filemtd_write
+ ****************************************************************************/
+
+static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset, 
+                    FAR const void *src, size_t len)
+{
+  FAR const uint8_t *pin  = (FAR const uint8_t *)src;
+  FAR uint8_t       *pout;
+  char               buf[128];
+  int                buflen = 0;
+  uint8_t            oldvalue;
+  uint8_t            srcvalue;
+  uint8_t            newvalue;
+  size_t             seekpos;
+
+  /* Set the starting location in the file */
+
+  seekpos = priv->offset + offset;
+
+  while (len-- > 0)
+    {
+      if (buflen == 0)
+        {
+          /* Read more data from the file */
+
+          lseek(priv->fd, seekpos, SEEK_SET);
+          buflen = read(priv->fd, buf, sizeof(buf));
+          pout = (FAR uint8_t *) buf;
+        }
+
+      /* Get the source and destination values */
+
+      oldvalue = *pout;
+      srcvalue = *pin++;
+
+      /* Get the new destination value, accounting for bits that cannot be
+       * changes because they are not in the erased state.
+       */
+
+#if CONFIG_FILEMTD_ERASESTATE == 0xff
+      newvalue = oldvalue & srcvalue; /* We can only clear bits */
+#else /* CONFIG_FILEMTD_ERASESTATE == 0x00 */
+      newvalue = oldvalue | srcvalue; /* We can only set bits */
+#endif
+
+      /* Report any attempt to change the value of bits that are not in the
+       * erased state.
+       */
+
+#ifdef CONFIG_DEBUG
+      if (newvalue != srcvalue)
+        {
+          dbg("ERROR: Bad write: source=%02x dest=%02x result=%02x\n",
+              srcvalue, oldvalue, newvalue);
+        }
+#endif
+
+      /* Write the modified value to simulated FLASH */
+
+      *pout++ = newvalue;
+      buflen--;
+
+      /* If our buffer is full, then seek back to beginning of 
+       * the file and write the buffer contents 
+       */
+
+      if (buflen == 0)
+        { 
+          lseek(priv->fd, seekpos, SEEK_SET);
+          write(priv->fd, buf, sizeof(buf));
+          seekpos += sizeof(buf);
+        } 
+    }
+
+  /* Write remaining bytes */
+
+  if (buflen != 0)
+    {
+      lseek(priv->fd, seekpos, SEEK_SET);
+      write(priv->fd, buf, sizeof(buf));
+    }
+
+  return len;
+}
+
+/****************************************************************************
+ * Name: filemtd_read
+ ****************************************************************************/
+
+static ssize_t filemtd_read(FAR struct file_dev_s *priv, unsigned char *buffer,
+                 size_t offsetbytes, unsigned int nbytes)
+{
+  /* Set the starting location in the file */
+
+  lseek(priv->fd, priv->offset + offsetbytes, SEEK_SET);
+
+  return read(priv->fd, buffer, nbytes);
+}
+
+/****************************************************************************
+ * Name: file_erase
+ ****************************************************************************/
+
+static int file_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
+{
+  FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
+  size_t    nbytes;
+  size_t    offset;
+  char      buffer[128];
+
+  DEBUGASSERT(dev);
+
+  /* Don't let the erase exceed the original size of the file */
+
+  if (startblock >= priv->nblocks)
+    {
+      return 0;
+    }
+
+  if (startblock + nblocks > priv->nblocks)
+    {
+      nblocks = priv->nblocks - startblock;
+    }
+
+  /* Convert the erase block to a logical block and the number of blocks
+   * in logical block numbers
+   */
+
+  startblock *= FILEMTD_BLKPER;
+  nblocks    *= FILEMTD_BLKPER;
+
+  /* Get the offset corresponding to the first block and the size
+   * corresponding to the number of blocks.
+   */
+
+  offset = startblock * CONFIG_FILEMTD_BLOCKSIZE;
+  nbytes = nblocks * CONFIG_FILEMTD_BLOCKSIZE;
+
+  /* Then erase the data in the file */
+
+  lseek(priv->fd, priv->offset + offset, SEEK_SET);
+  memset(buffer, CONFIG_FILEMTD_ERASESTATE, sizeof(buffer));
+  while (nbytes)
+    {
+      write(priv->fd, buffer, sizeof(buffer));
+      nbytes -= sizeof(buffer); 
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: file_bread
+ ****************************************************************************/
+
+static ssize_t file_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
+                          FAR uint8_t *buf)
+{
+  FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
+  off_t offset;
+  off_t maxblock;
+  size_t nbytes;
+
+  DEBUGASSERT(dev && buf);
+
+  /* Don't let the read exceed the original size of the file */
+
+  maxblock = priv->nblocks * FILEMTD_BLKPER;
+  if (startblock >= maxblock)
+    {
+      return 0;
+    }
+
+  if (startblock + nblocks > maxblock)
+    {
+      nblocks = maxblock - startblock;
+    }
+
+  /* Get the offset corresponding to the first block and the size
+   * corresponding to the number of blocks.
+   */
+
+  offset = startblock * CONFIG_FILEMTD_BLOCKSIZE;
+  nbytes = nblocks * CONFIG_FILEMTD_BLOCKSIZE;
+
+  /* Then read the data from the file */
+
+  filemtd_read(priv, buf, offset, nbytes);
+  return nblocks;
+}
+
+/****************************************************************************
+ * Name: file_bwrite
+ ****************************************************************************/
+
+static ssize_t file_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
+                          size_t nblocks, FAR const uint8_t *buf)
+{
+  FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
+  off_t offset;
+  off_t maxblock;
+  size_t nbytes;
+
+  DEBUGASSERT(dev && buf);
+
+  /* Don't let the write exceed the original size of the file */
+
+  maxblock = priv->nblocks * FILEMTD_BLKPER;
+  if (startblock >= maxblock)
+    {
+      return 0;
+    }
+
+  if (startblock + nblocks > maxblock)
+    {
+      nblocks = maxblock - startblock;
+    }
+
+  /* Get the offset corresponding to the first block and the size
+   * corresponding to the number of blocks.
+   */
+
+  offset = startblock * CONFIG_FILEMTD_BLOCKSIZE;
+  nbytes = nblocks * CONFIG_FILEMTD_BLOCKSIZE;
+
+  /* Then write the data to the file */
+
+  filemtd_write(priv, offset, buf, nbytes);
+  return nblocks;
+}
+
+/****************************************************************************
+ * Name: file_byteread
+ ****************************************************************************/
+
+static ssize_t file_byteread(FAR struct mtd_dev_s *dev, off_t offset,
+                            size_t nbytes, FAR uint8_t *buf)
+{
+  FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
+
+  DEBUGASSERT(dev && buf);
+
+  /* Don't let read read past end of buffer */
+
+  if (offset + nbytes > priv->nblocks * CONFIG_FILEMTD_ERASESIZE)
+   {
+     return 0;
+   }
+
+  filemtd_read(priv, buf, offset, nbytes);
+  return nbytes;
+}
+
+/****************************************************************************
+ * Name: file_bytewrite
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_BYTE_WRITE
+static ssize_t file_bytewrite(FAR struct mtd_dev_s *dev, off_t offset,
+                             size_t nbytes, FAR const uint8_t *buf)
+{
+  FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
+  off_t maxoffset;
+
+  DEBUGASSERT(dev && buf);
+
+  /* Don't let the write exceed the original size of the file */
+
+  maxoffset = priv->nblocks * CONFIG_FILEMTD_ERASESIZE;
+  if (offset + nbytes > maxoffset)
+    {
+      return 0;
+    }
+
+  /* Then write the data to the file */
+
+  filemtd_write(priv, offset, buf, nbytes);
+  return nbytes;
+}
+#endif
+
+/****************************************************************************
+ * Name: file_ioctl
+ ****************************************************************************/
+
+static int file_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
+{
+  FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev;
+  int ret = -EINVAL; /* Assume good command with bad parameters */
+
+  switch (cmd)
+    {
+      case MTDIOC_GEOMETRY:
+        {
+          FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg);
+          if (geo)
+            {
+              /* Populate the geometry structure with information need to know
+               * the capacity and how to access the device.
+               */
+
+              geo->blocksize    = CONFIG_FILEMTD_BLOCKSIZE;
+              geo->erasesize    = CONFIG_FILEMTD_ERASESIZE;
+              geo->neraseblocks = priv->nblocks;
+              ret               = OK;
+          }
+        }
+        break;
+
+      case MTDIOC_XIPBASE:
+        ret = -ENOTTY; /* Bad command */
+        break;
+
+      case MTDIOC_BULKERASE:
+        {
+            /* Erase the entire device */
+
+            file_erase(dev, 0, priv->nblocks);
+            ret = OK;
+        }
+        break;
+
+      default:
+        ret = -ENOTTY; /* Bad command */
+        break;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: filemtd_initialize
+ *
+ * Description:
+ *   Create and initialize a FILE MTD device instance.
+ *
+ * Input Parameters:
+ *   path - Path name of the file backing the MTD device
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset)
+{
+  FAR struct file_dev_s *priv;
+  struct stat sb;
+  size_t nblocks;
+  size_t filelen;
+  int    mode, ret;
+
+  /* Create an instance of the FILE MTD device state structure */
+
+  priv = (FAR struct file_dev_s *)kmm_zalloc(sizeof(struct file_dev_s));
+  if (!priv)
+    {
+      fdbg("Failed to allocate the FILE MTD state structure\n");
+      return NULL;
+    }
+
+  /* Determine the file open mode */
+
+  mode = O_RDOK;
+#ifdef CONFIG_FS_WRITABLE
+  mode |= O_WROK;
+#endif
+
+  /* Stat the file */
+
+  ret = stat(path, &sb);
+  if (ret < 0)
+    {
+      dbg("Failed to stat %s: %d\n", path, get_errno());
+      return NULL;
+    }
+
+  filelen = sb.st_size;
+
+  /* Try to open the file */
+
+  priv->fd = open(path, mode);
+  if (priv->fd == -1)
+    {
+      fdbg("Failed to open the FILE MTD file %s\n", path);
+      kmm_free(priv);
+      return NULL;
+    }
+
+  /* Force the size to be an even number of the erase block size */
+
+  nblocks = (filelen - offset) / CONFIG_FILEMTD_ERASESIZE;
+  if (nblocks < 3)
+    {
+      fdbg("Need to provide at least three full erase block\n");
+      kmm_free(priv);
+      return NULL;
+    }
+
+  /* Perform initialization as necessary. (unsupported methods were
+   * nullified by kmm_zalloc).
+   */
+
+  priv->mtd.erase  = file_erase;
+  priv->mtd.bread  = file_bread;
+  priv->mtd.bwrite = file_bwrite;
+  priv->mtd.read   = file_byteread;
+#ifdef CONFIG_MTD_BYTE_WRITE
+  priv->mtd.write  = file_bytewrite;
+#endif
+  priv->mtd.ioctl  = file_ioctl;
+  priv->offset     = offset;
+  priv->nblocks    = nblocks;
+
+  /* Register the MTD with the procfs system if enabled */
+
+#ifdef CONFIG_MTD_REGISTRATION
+  mtd_register(&priv->mtd, "filemtd");
+#endif
+
+  return &priv->mtd;
+}
+
+/****************************************************************************
+ * Name: filemtd_teardown
+ *
+ * Description:
+ *   Teardown a previously created filemtd device.
+ *
+ * Input Parameters:
+ *   path - Path name of the file backing the MTD device
+ *
+ ****************************************************************************/
+
+void filemtd_teardown(FAR struct mtd_dev_s *dev)
+{
+  FAR struct file_dev_s *priv;
+
+  /* Close the enclosed file */
+
+  priv = (FAR struct file_dev_s *) dev;
+  close(priv->fd);
+
+  /* Register the MTD with the procfs system if enabled */
+
+#ifdef CONFIG_MTD_REGISTRATION
+  mtd_unregister(&priv->mtd);
+#endif
+
+  /* Free the memory */
+
+  kmm_free(priv);
+}
+
diff --git a/drivers/mtd/mtd_procfs.c b/drivers/mtd/mtd_procfs.c
index 2f640b1a3f00ce36f39f535367a95c520d00fda8..b410df87565f8b49265f87a39ad4fe5843bd7286 100644
--- a/drivers/mtd/mtd_procfs.c
+++ b/drivers/mtd/mtd_procfs.c
@@ -363,4 +363,45 @@ int mtd_register(FAR struct mtd_dev_s *mtd, FAR const char *name)
   return OK;
 }
 
+/****************************************************************************
+ * Name: mtd_unregister
+ *
+ * Description:
+ *   Un-Registers an MTD device with the procfs file system.
+ *
+ * In an embedded system, this all is really unnecessary, but is provided
+ * in the procfs system simply for information purposes (if desired).
+ *
+ ****************************************************************************/
+
+int mtd_unregister(FAR struct mtd_dev_s *mtd)
+{
+  FAR struct mtd_dev_s *plast;
+
+  /* Remove the MTD from the list of registered devices */
+
+  if (g_pfirstmtd == mtd)
+    {
+      g_pfirstmtd = mtd->pnext;
+    }
+  else
+    {
+      /* Remove from middle of list */
+
+      plast = g_pfirstmtd;
+      while (plast->pnext != mtd)
+        {
+          /* Skip to next entry as long as there is one */
+
+          plast = plast->pnext;
+        }
+
+      /* Now remove at this location */
+
+      plast->pnext = mtd->pnext;
+    }
+
+  return OK;
+}
+
 #endif /* !CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_PROCFS */
diff --git a/include/nuttx/mtd/mtd.h b/include/nuttx/mtd/mtd.h
index 4bd25a612f06dd75522e7feb483505f7503b0dc1..367fbad1b8a7dfdc7e5091b3ece1e3d1a0109577 100644
--- a/include/nuttx/mtd/mtd.h
+++ b/include/nuttx/mtd/mtd.h
@@ -524,6 +524,18 @@ FAR struct mtd_dev_s *s25fl1_initialize(FAR struct qspi_dev_s *qspi,
 
 FAR struct mtd_dev_s *up_flashinitialize(void);
 
+/****************************************************************************
+ * Name: up_flashinitialize
+ *
+ * Description:
+ *   Create a file backed MTD device.
+ *
+ ****************************************************************************/
+
+FAR struct mtd_dev_s *filemtd_initialize(FAR const char *path, size_t offset);
+
+void filemtd_teardown(FAR struct mtd_dev_s* mtd);
+
 /****************************************************************************
  * Name: mtd_register
  *
@@ -541,6 +553,21 @@ FAR struct mtd_dev_s *up_flashinitialize(void);
 int mtd_register(FAR struct mtd_dev_s *mtd, FAR const char *name);
 #endif
 
+/****************************************************************************
+ * Name: mtd_unregister
+ *
+ * Description:
+ *   Un-registers an MTD device with the procfs file system.
+ *
+ * In an embedded system, this all is really unnecessary, but is provided
+ * in the procfs system simply for information purposes (if desired).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_REGISTRATION
+int mtd_unregister(FAR struct mtd_dev_s *mtd);
+#endif
+
 #undef EXTERN
 #ifdef __cplusplus
 }