diff --git a/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html
index a9bf7df8d3ad70f688ef677e407a7d9b1c7c6259..dec31beea36474cb48e91af1e15234187858285f 100644
--- a/Documentation/NuttxPortingGuide.html
+++ b/Documentation/NuttxPortingGuide.html
@@ -1805,6 +1805,7 @@ extern void up_ledoff(int led);
     Each SPI device driver must implement an instance of <code>struct spi_ops_s</code>.
     That structure defines a call table with the following methods:
     <ul>
+     <p><code>void lock(FAR struct spi_dev_s *dev);</code></p>
      <p><code>void select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected);</code><br>
      <code>uint32 setfrequency(FAR struct spi_dev_s *dev, uint32 frequency);</code><br>
      <code>void setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);</code><br>
diff --git a/TODO b/TODO
index 83c451eb0811eb2fc682b187f62858b4e19e1530..c5e4aa36c4ee1e7631c5c14b6be981f64c6ede7f 100644
--- a/TODO
+++ b/TODO
@@ -26,6 +26,7 @@ NuttX TODO List (Last updated September 16, 2009)
   (8)  ARM/LPC214x (arch/arm/src/lpc214x/)
   (3)  ARM/STR71x (arch/arm/src/str71x/)
   (3)  ARM/LM3S6918 (arch/arm/src/lm3s/)
+  (5)  ARM/STM32 (arch/arm/src/stm32/)
   (4)  pjrc-8052 / MCS51 (arch/pjrc-8051/)
   (2)  Hitachi/Renesas SH-1 (arch/sh/src/sh1)
   (4)  Renesas M16C/26 (arch/sh/src/m16c)
@@ -641,6 +642,29 @@ o ARM/LM3S6918 (arch/arm/src/lm3s/)
   Status:      Open
   Priority:    Low -- unless some dependency-related build issues is discovered.
 
+o ARM/STM32 (arch/arm/src/stm32/)
+  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Description: DMA subsystem is untested.
+  Status:      Open
+  Priority:    Low -- for now
+
+  Description: NOR Flash driver and FTL layer to support a file system.
+  Status:      Open
+  Priority:    Low
+
+  Description: MMC/SD SDIO driver needed.
+  Status:      Open
+  Priority:    Medium
+
+  Description  USB device-side driver
+  Status:      Open
+  Priority:    Medium-High
+  
+  Description: Framebuffer driver needed.
+  Status:      Open
+  Priority:    High
+
 o pjrc-8052 / MCS51 (arch/pjrc-8051/)
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/arch/arm/src/imx/imx_spi.c b/arch/arm/src/imx/imx_spi.c
index f1b3262a0340fdd7643e486fb1bb6652dead6fc9..46cfb691347d772f907831e6c13edc97dfc89b8d 100755
--- a/arch/arm/src/imx/imx_spi.c
+++ b/arch/arm/src/imx/imx_spi.c
@@ -184,6 +184,7 @@ static void   spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t
 
 static const struct spi_ops_s g_spiops =
 {
+  .lock         = 0,                /* Not yet implemented */
   .select       = imx_spiselect,    /* Provided externally by board logic */
   .setfrequency = spi_setfrequency,
   .setmode      = spi_setmode,
diff --git a/arch/arm/src/lm3s/lm3s_ssi.c b/arch/arm/src/lm3s/lm3s_ssi.c
index 65b01b625e34c8e10005bdb8cfa3fb25ec514ddf..2821dc87ea926f4f3f3de4ae2eb077fb143f8aa1 100755
--- a/arch/arm/src/lm3s/lm3s_ssi.c
+++ b/arch/arm/src/lm3s/lm3s_ssi.c
@@ -251,6 +251,7 @@ static void   ssi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t
 
 static const struct spi_ops_s g_spiops =
 {
+  .lock         = 0,                 /* Not yet implemented */
   .select       = lm3s_spiselect,    /* Provided externally by board logic */
   .setfrequency = ssi_setfrequency,
   .setmode      = ssi_setmode,
diff --git a/arch/arm/src/stm32/stm32_internal.h b/arch/arm/src/stm32/stm32_internal.h
index e5d429be73e963ac822a5df4a4ce058694431d70..58be75b617e600d40831d2bdc6935a93f6666f0c 100755
--- a/arch/arm/src/stm32/stm32_internal.h
+++ b/arch/arm/src/stm32/stm32_internal.h
@@ -610,9 +610,6 @@ EXTERN int stm32_ethinitialize(int intf);
  *   2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your
  *      board-specific logic.  These functions will perform chip selection and
  *      status operations using GPIOs in the way your board is configured.
- *      The select() methods must call stm32_spitake() when the chip is selected
- *      and stm32_spigive() when the chip is deselected.  This assures mutually
- *      exclusive access to the SPI for the duration while a chip is selected.
  *   3. Add a calls to up_spiinitialize() in your low level application
  *      initialization logic
  *   4. The handle returned by up_spiinitialize() may then be used to bind the
@@ -631,20 +628,6 @@ EXTERN ubyte stm32_spi2status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
 EXTERN void  stm32_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected);
 EXTERN ubyte stm32_spi3status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
 
-/************************************************************************************
- * Name: stm32_spitake() and stm32_spigive()
- *
- * Description:
- *   The stm32_spi1/2/3select() and stm32_spi1/2/3status() methods must call
- *   stm32_spitake() when the chip is selected and stm32_spigive() when the chip is
- *   deselected.  This assures mutually exclusive access to the SPI for the duration
- *   while a chip is selected.
- *
- ************************************************************************************/
-
-EXTERN void stm32_spitake(FAR struct spi_dev_s *dev);
-EXTERN void stm32_spigive(FAR struct spi_dev_s *dev);
-
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/arch/arm/src/stm32/stm32_spi.c b/arch/arm/src/stm32/stm32_spi.c
index abd9538bb4f5a2de92696ec4be7b6bb1621a35b6..2ca8989c8b6d55f4262b7b0b146876c962ebcc83 100755
--- a/arch/arm/src/stm32/stm32_spi.c
+++ b/arch/arm/src/stm32/stm32_spi.c
@@ -46,9 +46,6 @@
  *   2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your
  *      board-specific logic.  These functions will perform chip selection and
  *      status operations using GPIOs in the way your board is configured.
- *      The select() methods must call stm32_spitake() when the chip is selected
- *      and stm32_spigive() when the chip is deselected.  This assures mutually
- *      exclusive access to the SPI for the duration while a chip is selected.
  *   3. Add a calls to up_spiinitialize() in your low level application
  *      initialization logic
  *   4. The handle returned by up_spiinitialize() may then be used to bind the
@@ -119,6 +116,10 @@ struct stm32_spidev_s
   struct spi_dev_s spidev;     /* Externally visible part of the SPI interface */
   uint32           spibase;    /* SPIn base address */
   uint32           spiclock;   /* Clocking for the SPI module */
+  uint32           frequency;  /* Requested clock frequency */
+  uint32           actual;     /* Actual clock frequency */
+  ubyte            nbits;      /* Width of work in bits (8 or 16) */
+  ubyte            mode;       /* Mode 0,1,2,3 */
 #ifdef CONFIG_STM32_SPI_INTERRUPTS
   ubyte            spiirq;     /* SPI IRQ number */
 #endif
@@ -167,6 +168,7 @@ static inline void    spi_dmatxstart(FAR struct stm32_spidev_s *priv);
 
 /* SPI methods */
 
+static int            spi_lock(FAR struct spi_dev_s *dev, boolean lock);
 static uint32         spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency);
 static void           spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
 static void           spi_setbits(FAR struct spi_dev_s *dev, int nbits);
@@ -191,6 +193,7 @@ static void           spi_portinitialize(FAR struct stm32_spidev_s *priv);
 #ifdef CONFIG_STM32_SPI1
 static const struct spi_ops_s g_sp1iops =
 {
+  .lock              = spi_lock,
   .select            = stm32_spi1select,
   .setfrequency      = spi_setfrequency,
   .setmode           = spi_setmode,
@@ -224,6 +227,7 @@ static struct stm32_spidev_s g_spi1dev =
 #ifdef CONFIG_STM32_SPI2
 static const struct spi_ops_s g_sp2iops =
 {
+  .lock              = spi_lock,
   .select            = stm32_spi2select,
   .setfrequency      = spi_setfrequency,
   .setmode           = spi_setmode,
@@ -257,6 +261,7 @@ static struct stm32_spidev_s g_spi2dev =
 #ifdef CONFIG_STM32_SPI3
 static const struct spi_ops_s g_sp3iops =
 {
+  .lock              = spi_lock,
   .select            = stm32_spi3select,
   .setfrequency      = spi_setfrequency,
   .setmode           = spi_setmode,
@@ -664,6 +669,51 @@ static void spi_modifycr1(FAR struct stm32_spidev_s *priv, uint16 setbits, uint1
   spi_putreg(priv, STM32_SPI_CR1_OFFSET, cr1);
 }
 
+/****************************************************************************
+ * Name: spi_lock
+ *
+ * Description:
+ *   On SPI busses where there are multiple devices, it will be necessary to
+ *   lock SPI to have exclusive access to the busses for a sequence of
+ *   transfers.  The bus should be locked before the chip is selected. After
+ *   locking the SPI bus, the caller should then also call the setfrequency,
+ *   setbits, and setmode methods to make sure that the SPI is properly
+ *   configured for the device.  If the SPI buss is being shared, then it
+ *   may have been left in an incompatible state.
+ *
+ * Input Parameters:
+ *   dev  - Device-specific state data
+ *   lock - TRUE: Lock spi bus, FALSE: unlock SPI bus
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static int spi_lock(FAR struct spi_dev_s *dev, boolean lock)
+{
+  FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
+
+  if (lock)
+    {
+      /* Take the semaphore (perhaps waiting) */
+
+      while (sem_wait(&priv->exclsem) != 0)
+        {
+          /* The only case that an error should occur here is if the wait was awakened
+           * by a signal.
+           */
+
+          ASSERT(errno == EINTR);
+        }
+    }
+  else
+    {
+      (void)sem_post(&priv->exclsem);
+    }
+  return OK;
+}
+
 /************************************************************************************
  * Name: spi_setfrequency
  *
@@ -685,67 +735,74 @@ static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency)
   uint16 setbits;
   uint32 actual;
 
-  /* Choices are limited by PCLK frequency with a set of divisors */
+  /* Has the frequency changed? */
 
-  if (frequency >= priv->spiclock >> 1)
+  if (frequency != priv->frequency)
     {
-      /* More than fPCLK/2.  This is as fast as we can go */
+      /* Choices are limited by PCLK frequency with a set of divisors */
 
-      setbits = SPI_CR1_FPCLCKd2; /* 000: fPCLK/2 */
-      actual = priv->spiclock >> 1;
-    }
-  else if (frequency >= priv->spiclock >> 2)
-    {
-      /* Between fPCLCK/2 and fPCLCK/4, pick the slower */
+      if (frequency >= priv->spiclock >> 1)
+        {
+          /* More than fPCLK/2.  This is as fast as we can go */
 
-      setbits = SPI_CR1_FPCLCKd4; /* 001: fPCLK/4 */
-      actual = priv->spiclock >> 2;
-    }
-  else if (frequency >= priv->spiclock >> 3)
-    {
-      /* Between fPCLCK/4 and fPCLCK/8, pick the slower */
+          setbits = SPI_CR1_FPCLCKd2; /* 000: fPCLK/2 */
+          actual = priv->spiclock >> 1;
+        }
+      else if (frequency >= priv->spiclock >> 2)
+        {
+          /* Between fPCLCK/2 and fPCLCK/4, pick the slower */
 
-      setbits = SPI_CR1_FPCLCKd8; /* 010: fPCLK/8 */
-      actual = priv->spiclock >> 3;
-    }
-  else if (frequency >= priv->spiclock >> 4)
-    {
-      /* Between fPCLCK/8 and fPCLCK/16, pick the slower */
+          setbits = SPI_CR1_FPCLCKd4; /* 001: fPCLK/4 */
+          actual = priv->spiclock >> 2;
+       }
+      else if (frequency >= priv->spiclock >> 3)
+        {
+          /* Between fPCLCK/4 and fPCLCK/8, pick the slower */
 
-     setbits = SPI_CR1_FPCLCKd16; /* 011: fPCLK/16 */
-      actual = priv->spiclock >> 4;
-    }
-  else if (frequency >= priv->spiclock >> 5)
-    {
-      /* Between fPCLCK/16 and fPCLCK/32, pick the slower */
+          setbits = SPI_CR1_FPCLCKd8; /* 010: fPCLK/8 */
+          actual = priv->spiclock >> 3;
+        }
+      else if (frequency >= priv->spiclock >> 4)
+        {
+          /* Between fPCLCK/8 and fPCLCK/16, pick the slower */
 
-      setbits = SPI_CR1_FPCLCKd32; /* 100: fPCLK/32 */
-      actual = priv->spiclock >> 5;
-    }
-  else if (frequency >= priv->spiclock >> 6)
-    {
-      /* Between fPCLCK/32 and fPCLCK/64, pick the slower */
+          setbits = SPI_CR1_FPCLCKd16; /* 011: fPCLK/16 */
+          actual = priv->spiclock >> 4;
+        }
+      else if (frequency >= priv->spiclock >> 5)
+        {
+          /* Between fPCLCK/16 and fPCLCK/32, pick the slower */
 
-      setbits = SPI_CR1_FPCLCKd64; /*  101: fPCLK/64 */
-      actual = priv->spiclock >> 6;
-    }
-  else if (frequency >= priv->spiclock >> 7)
-    {
-      /* Between fPCLCK/64 and fPCLCK/128, pick the slower */
+          setbits = SPI_CR1_FPCLCKd32; /* 100: fPCLK/32 */
+          actual = priv->spiclock >> 5;
+        }
+      else if (frequency >= priv->spiclock >> 6)
+        {
+          /* Between fPCLCK/32 and fPCLCK/64, pick the slower */
 
-      setbits = SPI_CR1_FPCLCKd128; /* 110: fPCLK/128 */
-      actual = priv->spiclock >> 7;
-    }
-  else
-    {
-      /* Less than fPCLK/128.  This is as slow as we can go */
+          setbits = SPI_CR1_FPCLCKd64; /*  101: fPCLK/64 */
+          actual = priv->spiclock >> 6;
+        }
+      else if (frequency >= priv->spiclock >> 7)
+        {
+          /* Between fPCLCK/64 and fPCLCK/128, pick the slower */
+
+          setbits = SPI_CR1_FPCLCKd128; /* 110: fPCLK/128 */
+          actual = priv->spiclock >> 7;
+        }
+      else
+        {
+          /* Less than fPCLK/128.  This is as slow as we can go */
  
-      setbits = SPI_CR1_FPCLCKd256; /* 111: fPCLK/256 */
-      actual = priv->spiclock >> 8;
-    }
+          setbits = SPI_CR1_FPCLCKd256; /* 111: fPCLK/256 */
+          actual = priv->spiclock >> 8;
+        }
 
-  spi_modifycr1(priv, setbits, SPI_CR1_BR_MASK);
-  return actual;
+      spi_modifycr1(priv, setbits, SPI_CR1_BR_MASK);
+      priv->frequency = frequency;
+      priv->actual    = actual;
+    }
+  return priv->actual;
 }
 
 /************************************************************************************
@@ -769,33 +826,41 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
   uint16 setbits;
   uint16 clrbits;
 
-  switch (mode)
+  /* Has the mode changed? */
+
+  if (mode != priv->mode)
     {
-    case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */
-      setbits = 0;
-      clrbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
-      break;
+      /* Yes... Set CR1 appropriately */
+
+      switch (mode)
+        {
+        case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */
+          setbits = 0;
+          clrbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
+          break;
  
-    case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
-      setbits = SPI_CR1_CPHA;
-      clrbits = SPI_CR1_CPOL;
-      break;
+        case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
+          setbits = SPI_CR1_CPHA;
+          clrbits = SPI_CR1_CPOL;
+          break;
  
-    case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
-      setbits = SPI_CR1_CPOL;
-      clrbits = SPI_CR1_CPHA;
-      break;
+        case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
+          setbits = SPI_CR1_CPOL;
+          clrbits = SPI_CR1_CPHA;
+          break;
  
-    case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
-      setbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
-      clrbits = 0;
-      break;
+        case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
+          setbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
+          clrbits = 0;
+          break;
  
-    default:
-      return;
-    }
+        default:
+          return;
+        }
 
-    spi_modifycr1(priv, setbits, clrbits);
+        spi_modifycr1(priv, setbits, clrbits);
+        priv->mode = mode;
+    }
 }
 
 /************************************************************************************
@@ -819,23 +884,31 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
   uint16 setbits;
   uint16 clrbits;
 
-  switch (nbits)
+  /* Has the number of bits changed? */
+
+  if (nbits != priv->nbits)
     {
-    case 8:
-      setbits = 0;
-      clrbits = SPI_CR1_DFF;
-      break;
+      /* Yes... Set CR1 appropriately */
+
+      switch (nbits)
+        {
+        case 8:
+          setbits = 0;
+          clrbits = SPI_CR1_DFF;
+          break;
  
-    case 16:
-      setbits = SPI_CR1_DFF;
-      clrbits = 0;
-      break;
+        case 16:
+          setbits = SPI_CR1_DFF;
+          clrbits = 0;
+          break;
 
-    default:
-      return;
-    }
+        default:
+          return;
+        }
 
-    spi_modifycr1(priv, setbits, clrbits);
+        spi_modifycr1(priv, setbits, clrbits);
+        priv->nbits = nbits;
+    }
 }
 
 /************************************************************************************
@@ -1094,8 +1167,12 @@ static void spi_portinitialize(FAR struct stm32_spidev_s *priv)
   setbits = SPI_CR1_MSTR|SPI_CR1_SSI|SPI_CR1_SSM;
   spi_modifycr1(priv, setbits, clrbits);
 
+  priv->nbits = 8;
+  priv->mode  = SPIDEV_MODE0;
+
   /* Select a default frequency of approx. 400KHz */
 
+  priv->frequency = 0;
   spi_setfrequency((FAR struct spi_dev_s *)priv, 400000);
 
   /* CRCPOLY configuration */
@@ -1227,37 +1304,4 @@ FAR struct spi_dev_s *up_spiinitialize(int port)
   return (FAR struct spi_dev_s *)priv;
 }
 
-/************************************************************************************
- * Name: stm32_spitake() and stm32_spigive()
- *
- * Description:
- *   The stm32_spi1/2/3select() and stm32_spi1/2/3status() methods must call
- *   stm32_spitake() when the chip is selected and stm32_spigive() when the chip is
- *   deselected.  This assures mutually exclusive access to the SPI for the duration
- *   while a chip is selected.
- *
- ************************************************************************************/
-
-void stm32_spitake(FAR struct spi_dev_s *dev)
-{
-  FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
-
-  /* Take the semaphore (perhaps waiting) */
-
-  while (sem_wait(&priv->exclsem) != 0)
-    {
-      /* The only case that an error should occur here is if the wait was awakened
-       * by a signal.
-       */
-
-      ASSERT(errno == EINTR);
-    }
-}
-
-void stm32_spigive(FAR struct spi_dev_s *dev)
-{
-  FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
-  (void)sem_post(&priv->exclsem);
-}
-
 #endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 || CONFIG_STM32_SPI3 */
diff --git a/arch/z80/src/ez80/ez80_spi.c b/arch/z80/src/ez80/ez80_spi.c
index 8e34de10e6b3226fa7a5d1a1adb57d5daf7b31c0..d051f074fccb91b1218a77aad140363408c05e0a 100755
--- a/arch/z80/src/ez80/ez80_spi.c
+++ b/arch/z80/src/ez80/ez80_spi.c
@@ -77,6 +77,7 @@ static void   spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t
 
 static const struct spi_ops_s g_spiops =
 {
+  0,                 /* lock() method not yet implemented */
   ez80_spiselect,    /* Provided externally by board logic */
   spi_setfrequency,
   spi_setmode,
@@ -85,6 +86,7 @@ static const struct spi_ops_s g_spiops =
   spi_send,
   spi_sndblock,
   spi_recvblock,
+  0                  /* registercallback not yet implemented */
 };
 
 /* This supports is only a single SPI bus/port.  If you port this to an
diff --git a/configs/mcu123-lpc214x/src/up_spi.c b/configs/mcu123-lpc214x/src/up_spi.c
index c8cd831ba89f79154319c80c2273f15db04f9b3f..50d41cc906c56f53d234510646b7e4b43f6d6279 100644
--- a/configs/mcu123-lpc214x/src/up_spi.c
+++ b/configs/mcu123-lpc214x/src/up_spi.c
@@ -133,12 +133,14 @@ static void   spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t
 
 static const struct spi_ops_s g_spiops =
 {
+  .lock              = 0,                 /* Not yet implemented */
   .select            = spi_select,
   .setfrequency      = spi_setfrequency,
   .status            = spi_status,
   .send              = spi_send,
   .sndblock          = spi_sndblock,
   .recvblock         = spi_recvblock,
+  .registercallback  = 0,                 /* Not implemented */
 };
 
 static struct spi_dev_s g_spidev = { &g_spiops };
diff --git a/configs/olimex-strp711/src/up_spi.c b/configs/olimex-strp711/src/up_spi.c
index dc520449df02fff1f75d6533d6811b038163d4a7..04337445be5b25e7ba23a9b7ccbe19a59a6c087b 100644
--- a/configs/olimex-strp711/src/up_spi.c
+++ b/configs/olimex-strp711/src/up_spi.c
@@ -276,12 +276,14 @@ static void   spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t
 
 static const struct spi_ops_s g_spiops =
 {
+  .lock              = 0,                 /* Not yet implemented */
   .select            = spi_select,
   .setfrequency      = spi_setfrequency,
   .status            = spi_status,
   .send              = spi_send,
   .sndblock          = spi_sndblock,
   .recvblock         = spi_recvblock,
+  .registercallback  = 0,                 /* Not implemented */
 };
 
 #ifdef CONFIG_STR71X_BSPI0
diff --git a/configs/stm3210e-eval/src/stm3210e-internal.h b/configs/stm3210e-eval/src/stm3210e-internal.h
index 7d9f20e74c17d4a5a92f8079d3021a3d7d6ef020..18676957579ebdc79e85f57f43af359e5bf5d90e 100755
--- a/configs/stm3210e-eval/src/stm3210e-internal.h
+++ b/configs/stm3210e-eval/src/stm3210e-internal.h
@@ -70,11 +70,6 @@
 #define GPIO_LED3     (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTF|GPIO_PIN8)
 #define GPIO_LED4     (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_CLEAR|GPIO_PORTF|GPIO_PIN9)
 
-/* MMC/SD SPI1 chip select: PC.12 */
-
-#warning "MicoSD is on SDIO port, not SPI"
-#define GPIO_MMCSD_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN12)
-
 /* SPI FLASH chip select:  PA.4 */
 
 #define GPIO_FLASH_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|GPIO_OUTPUT_SET|GPIO_PORTB|GPIO_PIN2)
diff --git a/configs/stm3210e-eval/src/up_nsh.c b/configs/stm3210e-eval/src/up_nsh.c
index 5ce767b454676601569011ff01cff09eafee434d..01dcb440b7a0f4195aa6b42dbc897709f157e1b3 100755
--- a/configs/stm3210e-eval/src/up_nsh.c
+++ b/configs/stm3210e-eval/src/up_nsh.c
@@ -45,7 +45,10 @@
 #include <debug.h>
 #include <errno.h>
 
-#include <nuttx/spi.h>
+#ifdef CONFIG_STM32_SPI1
+#  include <nuttx/spi.h>
+#  include <nuttx/mtd.h>
+#endif
 #include <nuttx/mmcsd.h>
 
 /****************************************************************************
@@ -54,6 +57,10 @@
 
 /* Configuration ************************************************************/
 
+/* For now, don't build in any SPI1 support -- NSH is not using it */
+
+#undef CONFIG_STM32_SPI1
+
 /* PORT and SLOT number probably depend on the board configuration */
 
 /* Can't support USB features if USB is not enabled */
@@ -62,23 +69,8 @@
 #  undef CONFIG_EXAMPLES_NSH_HAVEUSBDEV
 #endif
 
-/* MMC/SD is on SPI1 */
-#warning "MicoSD is on SDIO port, not SPI"
-
-#ifndef CONFIG_STM32_SPI1
-#  undef CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO
-#  undef CONFIG_EXAMPLES_NSH_MMCSDSLOTNO
-#endif
-
-#if defined(CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO) && CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO != 0
-#  error MMC/SD is on SPI1
-#  undef CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO
-#  undef CONFIG_EXAMPLES_NSH_MMCSDSLOTNO
-#endif
-
 #if defined(CONFIG_EXAMPLES_NSH_MMCSDSLOTNO) && CONFIG_EXAMPLES_NSH_MMCSDSLOTNO != 0
 #  error "Only one MMC/SD slot"
-#  undef CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO
 #  undef CONFIG_EXAMPLES_NSH_MMCSDSLOTNO
 #endif
 
@@ -124,39 +116,44 @@ int nsh_archinitialize(void)
 {
 #ifdef CONFIG_STM32_SPI1
   FAR struct spi_dev_s *spi;
-  int ret;
+  FAR struct mtd_dev_s *mtd;
+#endif
 
-  /* Get the SPI port */
+  /* Configure SPI-based devices */
 
-  message("nsh_archinitialize: Initializing SPI port %d\n",
-          CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO);
+#ifdef CONFIG_STM32_SPI1
+  /* Get the SPI port */
 
-  spi = up_spiinitialize(CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO);
+  message("nsh_archinitialize: Initializing SPI port 0\n");
+  spi = up_spiinitialize(0);
   if (!spi)
     {
-      message("nsh_archinitialize: Failed to initialize SPI port %d\n",
-              CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO);
+      message("nsh_archinitialize: Failed to initialize SPI port 0\n");
       return -ENODEV;
     }
+  message("nsh_archinitialize: Successfully initialized SPI port 0\n");
 
-  message("nsh_archinitialize: Successfully initialized SPI port %d\n",
-          CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO);
-
-  /* Bind the SPI port to the slot */
-
-  message("nsh_archinitialize: Binding SPI port %d to MMC/SD slot %d\n",
-          CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO, CONFIG_EXAMPLES_NSH_MMCSDSLOTNO);
+  /* Now bind the SPI interface to the M25P64/128 SPI FLASH driver */
 
-  ret = mmcsd_spislotinitialize(CONFIG_EXAMPLES_NSH_MMCSDMINOR, CONFIG_EXAMPLES_NSH_MMCSDSLOTNO, spi);
-  if (ret < 0)
+  message("nsh_archinitialize: Bind SPI to the SPI flash driver\n");
+  mtd = m25p_initialize(spi);
+  if (!mtd)
     {
-      message("nsh_archinitialize: Failed to bind SPI port %d to MMC/SD slot %d: %d\n",
-              CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO, CONFIG_EXAMPLES_NSH_MMCSDSLOTNO, ret);
-      return ret;
+      message("nsh_archinitialize: Failed to bind SPI port 0 to the SPI FLASH driver\n");
+      return -ENODEV;
     }
-
-  message("nsh_archinitialize: Successfuly bound SPI port %d to MMC/SD slot %d\n",
-          CONFIG_EXAMPLES_NSH_MMCSDSPIPORTNO, CONFIG_EXAMPLES_NSH_MMCSDSLOTNO);
+  message("nsh_archinitialize: Successfully bound SPI port 0 to the SPI FLASH driver\n");
+#warning "Now what are we going to do with this SPI FLASH driver?"
 #endif
+
+  /* Create the SPI FLASH MTD instance */
+
+  /* Here we will eventually need to
+   * 1. Get the SDIO interface instance, and 
+   * 2. Bind it to the MMC/SD driver (slot CONFIG_EXAMPLES_NSH_MMCSDSLOTNO,
+   *    CONFIG_EXAMPLES_NSH_MMCSDMINOR).
+   */
+
+#warning "Missing MMC/SD device configuration"
   return OK;
 }
diff --git a/configs/stm3210e-eval/src/up_spi.c b/configs/stm3210e-eval/src/up_spi.c
index e3bcbf05a4d3ffc7c5622112972cccc35acbfa24..3c2c3e236841546803c35aeb8bccc902089fd66d 100755
--- a/configs/stm3210e-eval/src/up_spi.c
+++ b/configs/stm3210e-eval/src/up_spi.c
@@ -79,36 +79,6 @@
  * Private Functions
  ************************************************************************************/
 
-static void stm32_chipselect(FAR struct spi_dev_s *dev, uint32 pinset, boolean pinval, boolean selected)
-{
-  spidbg("devid: %d CS: %s pinset: %08x pinval: %s\n",
-         (int)devid, selected ? "assert" : "de-assert", pinset, pinval ? "HIGH" : "LOW");
-
-  /* If we are selecting the chip, then we must call stm32_spitake to assure that we
-   * have mutually exclusive access to the SPI bus while the chip is selected.
-   */
-
-  if (selected)
-    {
-      stm32_spitake(dev);
-    }
-
-  /* Then set the CHIP select.  Usually the chip select is LOW to select and HIGH, but
-   * that can vary from part to part.
-   */
-
-  stm32_gpiowrite(pinset, pinval);
-
-  /* If we just de-selected the chip, then we must call stm32_spigive to to relinquish
-   * our exclusive access to the SPI bus.  Now, any waiting threads can have the SPI.
-   */
-
-  if (!selected)
-    {
-      stm32_spigive(dev);
-    }
-}
-
 /************************************************************************************
  * Public Functions
  ************************************************************************************/
@@ -130,10 +100,8 @@ void weak_function stm32_spiinitialize(void)
    */
 
 #ifdef CONFIG_STM32_SPI1
-  /* Configure the SPI-based microSD and FLASH CS GPIO */
+  /* Configure the SPI-based FLASH CS GPIO */
 
-#warning "MicoSD is on SDIO port, not SPI"
-  stm32_configgpio(GPIO_MMCSD_CS);
   stm32_configgpio(GPIO_FLASH_CS);
 #endif
 }
@@ -154,9 +122,6 @@ void weak_function stm32_spiinitialize(void)
  *   2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your
  *      board-specific logic.  These functions will perform chip selection and
  *      status operations using GPIOs in the way your board is configured.
- *      The select() methods must call stm32_spitake() when the chip is selected
- *      and stm32_spigive() when the chip is deselected.  This assures mutually
- *      exclusive access to the SPI for the duration while a chip is selected.
  *   3. Add a calls to up_spiinitialize() in your low level application
  *      initialization logic
  *   4. The handle returned by up_spiinitialize() may then be used to bind the
@@ -171,17 +136,11 @@ void stm32_spi1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean s
 {
   spidbg("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
 
-  if (devid == SPIDEV_MMCSD)
-  {
-    /* Set the GPIO low to select and high to de-select */
-
-    stm32_chipselect(dev, GPIO_MMCSD_CS,!selected, selected);
-  }
-  else if (devid == SPIDEV_FLASH)
+  if (devid == SPIDEV_FLASH)
   {
     /* Set the GPIO low to select and high to de-select */
 
-    stm32_chipselect(dev, GPIO_FLASH_CS,!selected, selected);
+    stm32_gpiowrite(GPIO_FLASH_CS, !selected);
   }
 }
 
diff --git a/drivers/mtd/m25px.c b/drivers/mtd/m25px.c
index c94c72fa0b0e5c35174bacafa05b97781821bf6c..f41b49e4be4e31101e1e49e8d5bd3ab68998323c 100644
--- a/drivers/mtd/m25px.c
+++ b/drivers/mtd/m25px.c
@@ -65,7 +65,7 @@
  *  (32768 pages) * (256 bytes per page)
  */
 
-#define M25P_M25P64_SECTOR_SHIFT  16	/* Sector size 1 << 16 = 65,536 */
+#define M25P_M25P64_SECTOR_SHIFT  16    /* Sector size 1 << 16 = 65,536 */
 #define M25P_M25P64_NSECTORS      128
 #define M25P_M25P64_PAGE_SHIFT    8     /* Page size 1 << 8 = 256 */
 #define M25P_M25P64_NPAGES        32768
@@ -75,7 +75,7 @@
  *  (65536 pages) * (256 bytes per page)
  */
 
-#define M25P_M25P128_SECTOR_SHIFT 18	/* Sector size 1 << 18 = 262,144 */
+#define M25P_M25P128_SECTOR_SHIFT 18    /* Sector size 1 << 18 = 262,144 */
 #define M25P_M25P128_NSECTORS     64
 #define M25P_M25P128_PAGE_SHIFT   8     /* Page size 1 << 8 = 256 */
 #define M25P_M25P128_NPAGES       65536
@@ -129,7 +129,7 @@ struct m25p_dev_s
   FAR struct spi_dev_s *dev; /* Saved SPI interface instance */
   ubyte  sectorshift;        /* 16 or 18 */
   ubyte  pageshift;          /* 8 */
-  uint16 nsectors;			 /* 128 or 64 */
+  uint16 nsectors;           /* 128 or 64 */
   uint32 npages;             /* 32,768 or 65,536 */
 };
 
@@ -139,6 +139,8 @@ struct m25p_dev_s
 
 /* Helpers */
 
+static void m25p_lock(FAR struct spi_dev_s *dev);
+static inline void m25p_unlock(FAR struct spi_dev_s *dev);
 static inline int m25p_readid(struct m25p_dev_s *priv);
 static void m25p_waitwritecomplete(struct m25p_dev_s *priv);
 static void m25p_writeenable(struct m25p_dev_s *priv);
@@ -166,6 +168,42 @@ static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
  * Private Functions
  ************************************************************************************/
 
+/************************************************************************************
+ * Name: m25p_lock
+ ************************************************************************************/
+
+static void m25p_lock(FAR struct spi_dev_s *dev)
+{
+  /* On SPI busses where there are multiple devices, it will be necessary to
+   * lock SPI to have exclusive access to the busses for a sequence of
+   * transfers.  The bus should be locked before the chip is selected.
+   *
+   * This is a blocking call and will not return until we have exclusiv access to
+   * the SPI buss.  We will retain that exclusive access until the bus is unlocked.
+   */
+
+  (void)SPI_LOCK(dev, TRUE);
+
+  /* After locking the SPI bus, the we also need call the setfrequency, setbits, and
+   * setmode methods to make sure that the SPI is properly configured for the device.
+   * If the SPI buss is being shared, then it may have been left in an incompatible
+   * state.
+   */
+
+  SPI_SETMODE(dev, SPIDEV_MODE3);
+  SPI_SETBITS(dev, 8);
+  (void)SPI_SETFREQUENCY(dev, 20000000);
+}
+
+/************************************************************************************
+ * Name: m25p_unlock
+ ************************************************************************************/
+
+static inline void m25p_unlock(FAR struct spi_dev_s *dev)
+{
+  (void)SPI_LOCK(dev, FALSE);
+}
+
 /************************************************************************************
  * Name: m25p_readid
  ************************************************************************************/
@@ -178,11 +216,9 @@ static inline int m25p_readid(struct m25p_dev_s *priv)
 
   fvdbg("priv: %p\n", priv);
 
-  /* Select this FLASH part.  This is a blocking call and will not return
-   * until we have exclusiv access to the SPI buss.  We will retain that
-   * exclusive access until the chip is de-selected.
-   */
+  /* Lock the SPI bus, configure the bus, and select this FLASH part. */
 
+  m25p_lock(priv->dev);
   SPI_SELECT(priv->dev, SPIDEV_FLASH, TRUE);
 
   /* Send the "Read ID (RDID)" command and read the first three ID bytes */
@@ -192,12 +228,13 @@ static inline int m25p_readid(struct m25p_dev_s *priv)
   memory       = SPI_SEND(priv->dev, M25P_DUMMY);
   capacity     = SPI_SEND(priv->dev, M25P_DUMMY);
 
-  fvdbg("manufacturer: %02x memory: %02x capacity: %02x\n",
-        manufacturer, memory, capacity);
-
-  /* Deselect the FLASH */
+  /* Deselect the FLASH and unlock the bus */
 
   SPI_SELECT(priv->dev, SPIDEV_FLASH, FALSE);
+  m25p_unlock(priv->dev);
+
+  fvdbg("manufacturer: %02x memory: %02x capacity: %02x\n",
+        manufacturer, memory, capacity);
 
   /* Check for a valid manufacturer and memory type */
 
@@ -236,10 +273,7 @@ static void m25p_waitwritecomplete(struct m25p_dev_s *priv)
 {
   ubyte status;
 
-  /* Select this FLASH part.  This is a blocking call and will not return
-   * until we have exclusiv access to the SPI buss.  We will retain that
-   * exclusive access until the chip is de-selected.
-   */
+  /* Select this FLASH part */
 
   SPI_SELECT(priv->dev, SPIDEV_FLASH, TRUE);
 
@@ -269,10 +303,7 @@ static void m25p_waitwritecomplete(struct m25p_dev_s *priv)
 
 static void m25p_writeenable(struct m25p_dev_s *priv)
 {
-  /* Select this FLASH part.  This is a blocking call and will not return
-   * until we have exclusiv access to the SPI buss.  We will retain that
-   * exclusive access until the chip is de-selected.
-   */
+  /* Select this FLASH part */
 
   SPI_SELECT(priv->dev, SPIDEV_FLASH, TRUE);
 
@@ -308,10 +339,7 @@ static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t sector)
 
   m25p_writeenable(priv);
 
-  /* Select this FLASH part.  This is a blocking call and will not return
-   * until we have exclusiv access to the SPI buss.  We will retain that
-   * exclusive access until the chip is de-selected.
-   */
+  /* Select this FLASH part */
 
   SPI_SELECT(priv->dev, SPIDEV_FLASH, TRUE);
 
@@ -338,7 +366,7 @@ static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t sector)
  * Name:  m25p_bulkerase
  ************************************************************************************/
 
-static inline int  m25p_bulkerase(struct m25p_dev_s *priv)
+static inline int m25p_bulkerase(struct m25p_dev_s *priv)
 {
   fvdbg("priv: %p\n", priv);
 
@@ -354,10 +382,7 @@ static inline int  m25p_bulkerase(struct m25p_dev_s *priv)
 
   m25p_writeenable(priv);
 
-  /* Select this FLASH part.  This is a blocking call and will not return
-   * until we have exclusiv access to the SPI buss.  We will retain that
-   * exclusive access until the chip is de-selected.
-   */
+  /* Select this FLASH part */
 
   SPI_SELECT(priv->dev, SPIDEV_FLASH, TRUE);
 
@@ -395,10 +420,7 @@ static inline void m25p_pagewrite(struct m25p_dev_s *priv, FAR const ubyte *buff
 
   m25p_writeenable(priv);
   
-  /* Select this FLASH part.  This is a blocking call and will not return
-   * until we have exclusiv access to the SPI buss.  We will retain that
-   * exclusive access until the chip is de-selected.
-   */
+  /* Select this FLASH part */
 
   SPI_SELECT(priv->dev, SPIDEV_FLASH, TRUE);
 
@@ -433,12 +455,17 @@ static int m25p_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblock
 
   fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
 
+  /* Lock access to the SPI bus until we complete the erase */
+
+  m25p_lock(priv->dev);
   while (blocksleft-- > 0)
     {
-		m25p_sectorerase(priv, startblock);
-		startblock++;
-    }
+      /* Erase each sector */
 
+      m25p_sectorerase(priv, startblock);
+      startblock++;
+    }
+  m25p_unlock(priv->dev);
   return (int)nblocks;
 }
 
@@ -459,7 +486,7 @@ static ssize_t m25p_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nb
   nbytes = m25p_read(dev, startblock << priv->pageshift, nblocks << priv->pageshift, buffer);
   if (nbytes > 0)
     {
-	    return nbytes >> priv->pageshift;
+        return nbytes >> priv->pageshift;
     }
   return nbytes;
 }
@@ -476,13 +503,15 @@ static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t n
 
   fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
 
-  /* Write each page to FLASH */
+  /* Lock the SPI bus and write each page to FLASH */
 
+  m25p_lock(priv->dev);
   while (blocksleft-- > 0)
     {
       m25p_pagewrite(priv, buffer, startblock);
       startblock++;
    }
+  m25p_unlock(priv->dev);
 
   return nblocks;
 }
@@ -506,11 +535,9 @@ static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
 
   m25p_waitwritecomplete(priv);
 
-  /* Select this FLASH part.  This is a blocking call and will not return
-   * until we have exclusiv access to the SPI buss.  We will retain that
-   * exclusive access until the chip is de-selected.
-   */
+  /* Lock the SPI bus and select this FLASH part */
 
+  m25p_lock(priv->dev);
   SPI_SELECT(priv->dev, SPIDEV_FLASH, TRUE);
 
   /* Send "Read from Memory " instruction */
@@ -527,9 +554,10 @@ static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
 
   SPI_RECVBLOCK(priv->dev, buffer, nbytes);
 
-  /* Deselect the FLASH */
+  /* Deselect the FLASH and unlock the SPI bus */
 
   SPI_SELECT(priv->dev, SPIDEV_FLASH, FALSE);
+  m25p_unlock(priv->dev);
   fvdbg("return nbytes: %d\n", (int)nbytes);
   return nbytes;
 }
@@ -574,9 +602,11 @@ static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
 
       case MTDIOC_BULKERASE:
         {
-	        /* Erase the entire device */
+            /* Erase the entire device */
 
-	        ret = m25p_bulkerase(priv);
+            m25p_lock(priv->dev);
+            ret = m25p_bulkerase(priv);
+            m25p_unlock(priv->dev);
         }
         break;
  
@@ -634,12 +664,6 @@ FAR struct mtd_dev_s *m25p_initialize(FAR struct spi_dev_s *dev)
 
       SPI_SELECT(dev, SPIDEV_FLASH, FALSE);
 
-      /* Make sure that SPI is correctly configured from this FLASH */
-
-      SPI_SETMODE(dev, SPIDEV_MODE3);
-      SPI_SETBITS(dev, 8);
-      SPI_SETFREQUENCY(dev, 20000000);
-
       /* Identify the FLASH chip and get its capacity */
 
       ret = m25p_readid(priv);
diff --git a/include/nuttx/spi.h b/include/nuttx/spi.h
index 6630de158d21aaca3433da62281ffe201ff3442c..59203d0ec8e6ffa7dfe02c4c32865cf00921911d 100644
--- a/include/nuttx/spi.h
+++ b/include/nuttx/spi.h
@@ -49,6 +49,29 @@
 
 /* Access macros */
 
+/****************************************************************************
+ * Name: SPI_LOCK
+ *
+ * Description:
+ *   On SPI busses where there are multiple devices, it will be necessary to
+ *   lock SPI to have exclusive access to the busses for a sequence of
+ *   transfers.  The bus should be locked before the chip is selected. After
+ *   locking the SPI bus, the caller should then also call the setfrequency,
+ *   setbits, and setmode methods to make sure that the SPI is properly
+ *   configured for the device.  If the SPI buss is being shared, then it
+ *   may have been left in an incompatible state.
+ *
+ * Input Parameters:
+ *   dev  - Device-specific state data
+ *   lock - TRUE: Lock spi bus, FALSE: unlock SPI bus
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#define SPI_LOCK(d,l) ((d)->ops->lock ? (d)->ops->lock(d,l) : OK)
+
 /****************************************************************************
  * Name: SPI_SELECT
  *
@@ -296,6 +319,7 @@ enum spi_mode_e
 struct spi_dev_s;
 struct spi_ops_s
 {
+  int    (*lock)(FAR struct spi_dev_s *dev, boolean lock);
   void   (*select)(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected);
   uint32 (*setfrequency)(FAR struct spi_dev_s *dev, uint32 frequency);
   void   (*setmode)(FAR struct spi_dev_s *dev, enum spi_mode_e mode);