diff --git a/ChangeLog b/ChangeLog
index 0cfa7faacdffc2e09c4ef6694eb2c0700797009e..51abe18d080dca39a02f709d76092a420bac1ada 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -734,5 +734,8 @@
 	* examples/nsh: Added MMC/SD support for the LM3S6918
 	* arch/arm/src/lm3s: Fix logic for setting and clearing output GPIOs (critical
 	  fix!).
-	* drivers/mmcsd:  Correct frequency calculation based on CSD settings.
+	* drivers/mmcsd:  Found numerous errors in current MMC/SD SPI driver.  Bad frequency
+	  calculation based on CSD settings, inappropriate timeouts, odd code that looks like
+	  a bad search and replace.  Also needs support for SDHC ver 2.x.  New MMC/SD is
+	  largely redesigned and probably non-functional in the first check-in.
 
diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html
index 2fb6c734d6cef1fc95c9f03d8a92b5e547982f7f..7c22f7ea05b76b898023dfae8861d0a68f9d6cfe 100644
--- a/Documentation/NuttX.html
+++ b/Documentation/NuttX.html
@@ -8,7 +8,7 @@
   <tr align="center" bgcolor="#e4e4e4">
     <td>
       <h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
-      <p>Last Updated: May 23, 2009</p>
+      <p>Last Updated: May 26, 2009</p>
     </td>
   </tr>
 </table>
@@ -1424,7 +1424,10 @@ nuttx-0.4.7 2009-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
 	* examples/nsh: Added MMC/SD support for the LM3S6918
 	* arch/arm/src/lm3s: Fix logic for setting and clearing output GPIOs (critical
 	  fix!).
-	* drivers/mmcsd:  Correct frequency calculation based on CSD settings.
+	* drivers/mmcsd:  Found numerous errors in current MMC/SD SPI driver.  Bad frequency
+	  calculation based on CSD settings, inappropriate timeouts, odd code that looks like
+	  a bad search and replace.  Also needs support for SDHC ver 2.x.  New MMC/SD is
+	  largely redesigned and probably non-functional in the first check-in.
 
 pascal-0.1.3 2009-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
 
diff --git a/configs/README.txt b/configs/README.txt
index 096a6a54b801e9b1fe6b25d57f0ece85f543ab11..2dba9d0f52938aff3729fb9ac018e5269c919c71 100644
--- a/configs/README.txt
+++ b/configs/README.txt
@@ -286,6 +286,8 @@ defconfig -- This is a configuration file similar to the Linux
 		  driver. Default is one.
 		CONFIG_MMCSD_READONLY -  Provide read-only access.  Default is
 		  Read/Write
+		CONFIG_MMCSD_SPICLOCK - Maximum SPI clock to drive MMC/SD card.
+		  Default is 20MHz.
 
 	TCP/IP and UDP support via uIP
 		CONFIG_NET - Enable or disable all network features
diff --git a/configs/eagle100/httpd/defconfig b/configs/eagle100/httpd/defconfig
index 044d5c5cb1b4f26502255c53eb38c3325c79659f..e6b40982db0dfb228fc48e2901f50ef3b07b9642 100644
--- a/configs/eagle100/httpd/defconfig
+++ b/configs/eagle100/httpd/defconfig
@@ -350,8 +350,12 @@ CONFIG_FS_ROMFS=n
 #   Number of MMC/SD slots supported by the driver
 # CONFIG_MMCSD_READONLY
 #   Provide read-only access (default is read/write)
+# CONFIG_MMCSD_SPICLOCK - Maximum SPI clock to drive MMC/SD card.
+#   Default is 20MHz.
+#
 CONFIG_MMCSD_NSLOTS=1
 CONFIG_MMCSD_READONLY=n
+CONFIG_MMCSD_SPICLOCK=12500000
 
 #
 # TCP/IP and UDP support via uIP
diff --git a/configs/eagle100/nettest/defconfig b/configs/eagle100/nettest/defconfig
index c9679b551bef1cc58ff5e3e19b84a68dbeb0d786..fd74f7bedb1e8f09565baca8cb4d981bdbf74a8e 100644
--- a/configs/eagle100/nettest/defconfig
+++ b/configs/eagle100/nettest/defconfig
@@ -350,8 +350,12 @@ CONFIG_FS_ROMFS=n
 #   Number of MMC/SD slots supported by the driver
 # CONFIG_MMCSD_READONLY
 #   Provide read-only access (default is read/write)
+# CONFIG_MMCSD_SPICLOCK - Maximum SPI clock to drive MMC/SD card.
+#   Default is 20MHz.
+#
 CONFIG_MMCSD_NSLOTS=1
 CONFIG_MMCSD_READONLY=n
+CONFIG_MMCSD_SPICLOCK=12500000
 
 #
 # TCP/IP and UDP support via uIP
diff --git a/configs/eagle100/nsh/defconfig b/configs/eagle100/nsh/defconfig
index d40816e42277fee01f482a4b58482cd946004138..4bcb2decff1cf770b7f8756724880d980598b658 100644
--- a/configs/eagle100/nsh/defconfig
+++ b/configs/eagle100/nsh/defconfig
@@ -349,8 +349,12 @@ CONFIG_FS_ROMFS=n
 #   Number of MMC/SD slots supported by the driver
 # CONFIG_MMCSD_READONLY
 #   Provide read-only access (default is read/write)
+# CONFIG_MMCSD_SPICLOCK - Maximum SPI clock to drive MMC/SD card.
+#   Default is 20MHz.
+#
 CONFIG_MMCSD_NSLOTS=1
 CONFIG_MMCSD_READONLY=n
+CONFIG_MMCSD_SPICLOCK=12500000
 
 #
 # TCP/IP and UDP support via uIP
diff --git a/configs/eagle100/ostest/defconfig b/configs/eagle100/ostest/defconfig
index 41f811dd18e09297315f5c9c511eb742b6f7f962..cd430ca08dd6a495c2908945035ad111207af6b1 100644
--- a/configs/eagle100/ostest/defconfig
+++ b/configs/eagle100/ostest/defconfig
@@ -349,8 +349,12 @@ CONFIG_FS_ROMFS=n
 #   Number of MMC/SD slots supported by the driver
 # CONFIG_MMCSD_READONLY
 #   Provide read-only access (default is read/write)
+# CONFIG_MMCSD_SPICLOCK - Maximum SPI clock to drive MMC/SD card.
+#   Default is 20MHz.
+#
 CONFIG_MMCSD_NSLOTS=1
 CONFIG_MMCSD_READONLY=n
+CONFIG_MMCSD_SPICLOCK=12500000
 
 #
 # TCP/IP and UDP support via uIP
diff --git a/drivers/mmcsd/mmcsd_internal.h b/drivers/mmcsd/mmcsd_internal.h
index c49429a42b6c93b667205d9f4da217b23171fe54..1a81b59b5dca8d290902af7edc6895a1fe912921 100644
--- a/drivers/mmcsd/mmcsd_internal.h
+++ b/drivers/mmcsd/mmcsd_internal.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * drivers/mmcsd/mmcsd_internal.h
  *
- *   Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 20082009 Gregory Nutt. All rights reserved.
  *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
  *
  * Redistribution and use in source and binary forms, with or without
@@ -57,9 +57,16 @@
 
 /* Card type */
 
-#define MMCSD_CARDTYPE_UNKNOWN       0
-#define MMCSD_CARDTYPE_MMC           1
-#define MMCSD_CARDTYPE_SD            2
+#define MMCSD_CARDTYPE_UNKNOWN       0  /* Unknown card type */
+#define MMCSD_CARDTYPE_MMC           1  /* Bit 0: MMC card */
+#define MMCSD_CARDTYPE_SDV1          2  /* Bit 1: SD version 1.x */
+#define MMCSD_CARDTYPE_SDV2          4  /* Bit 1: SD version 2.x with byte addressing */
+#define MMCSD_CARDTYPE_BLOCK         8  /* Bit 2: SD version 2.x with block addressing */
+
+#define IS_MMC(t)   (((t) & MMCSD_CARDTYPE_MMC) != 0)
+#define IS_SD(t)    (((t) & (MMCSD_CARDTYPE_SDV1|MMCSD_CARDTYPE_SDV2)) != 0)
+#define IS_SDV2(t)  (((t) & MMCSD_CARDTYPE_SDV2) != 0)
+#define IS_BLOCK(t) (((t) & MMCSD_CARDTYPE_BLOCK) != 0)
 
 /****************************************************************************
  * Public Types
diff --git a/drivers/mmcsd/mmcsd_spi.c b/drivers/mmcsd/mmcsd_spi.c
index 71b7a5d038ba4c89d419a76bd7ac60f497006fd6..a4860cbb912b2cbe4e2d49aed0fdc83d87a72f3b 100644
--- a/drivers/mmcsd/mmcsd_spi.c
+++ b/drivers/mmcsd/mmcsd_spi.c
@@ -38,15 +38,17 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
-
+#include <nuttx/compiler.h>
 #include <sys/types.h>
 
 #include <stdio.h>
 #include <string.h>
+#include <time.h>
 #include <errno.h>
 #include <debug.h>
 
 #include <nuttx/arch.h>
+#include <nuttx/clock.h>
 #include <nuttx/spi.h>
 #include <nuttx/fs.h>
 #include <nuttx/mmcsd.h>
@@ -76,6 +78,10 @@
 #  define MMCSD_MODE 0444
 #endif
 
+#ifndef CONFIG_MMCSD_SPICLOCK
+#  define CONFIG_MMCSD_SPICLOCK 20000000
+#endif
+
 /* Slot struct info *********************************************************/
 /* Slot status definitions */
 
@@ -90,7 +96,9 @@
 #define MMCSD_CMDARG_NONE            0
 #define MMCSD_CMDARG_BLKLEN          1
 #define MMCSD_CMDARG_ADDRESS         2
-#define MMCSD_CMDARG_DUMMY           3
+#define MMCSD_CMDARG_NSECT           3
+#define MMCSD_CMDARG_1AA             4
+#define MMCSD_CMDARG_DUMMY           5
 
 /* These define the value returned by the MMC/SD command */
 
@@ -98,13 +106,26 @@
 #define MMCSD_CMDRESP_R1B            1
 #define MMCSD_CMDRESP_R2             2
 #define MMCSD_CMDRESP_R3             3
+#define MMCSD_CMDRESP_R7             4
 
-/* Fudge factor for SD read timeout: ~100msec, Write Time out ~250ms.  Units
- * of Hz.
+/* Time delays in units of the system clock. CLK_TCK is the number of clock
+ * ticks per second.
  */
 
-#define SD_READACCESSHZ              7
-#define SD_WRITEACCESSHZ             3
+#define MMCSD_DELAY_10MS             (CLK_TCK/100 + 1)
+#define MMCSD_DELAY_50MS             (CLK_TCK/20  + 1)
+#define MMCSD_DELAY_100MS            (CLK_TCK/10  + 1)
+#define MMCSD_DELAY_250MS            (CLK_TCK/4  + 1)
+#define MMCSD_DELAY_500MS            (CLK_TCK/2  + 1)
+#define MMCSD_DELAY_1SEC             (CLK_TCK + 1)
+
+#define ELAPSED_TIME(t)              (g_system_timer-(t))
+#define START_TIME                   (g_system_timer)
+
+/* SD read timeout: ~100msec, Write Time out ~250ms.  Units of clock ticks */
+
+#define SD_READACCESS                MMCSD_DELAY_100MS
+#define SD_WRITEACCESS               MMCSD_DELAY_250MS
 
 /****************************************************************************
  * Private Types
@@ -123,6 +144,8 @@ struct mmcsd_slot_s
   uint32 nsectors;       /* Number of blocks on the media */
   uint32 taccess;        /* Card access time */
   uint32 twrite;         /* Card write time */
+  uint32 ocr;            /* Last 4 bytes of OCR (R3) */
+  uint32 r7;             /* Last 4 bytes of R7 */
 };
 
 struct mmcsd_cmdinfo_s
@@ -146,6 +169,8 @@ static int    mmcsd_waitready(FAR struct mmcsd_slot_s *slot);
 static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
                 const struct mmcsd_cmdinfo_s *cmd, uint32 arg);
 static void   mmcsd_setblklen(FAR struct mmcsd_slot_s *slot, uint32 length);
+static uint32 mmcsd_nsac(FAR struct mmcsd_slot_s *slot, ubyte *csd, uint32 frequency);
+static uint32 mmcsd_taac(FAR struct mmcsd_slot_s *slot, ubyte *csd);
 static void   mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd);
 static void   mmcsd_checkwrprotect(FAR struct mmcsd_slot_s *slot, ubyte *csd);
 static int    mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
@@ -154,6 +179,13 @@ static int    mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
 #define mmcsd_getcsd(slot, csd) mmcsd_getcardinfo(slot, csd, &g_cmd9);
 #define mmcsd_getcid(slot, cid) mmcsd_getcardinfo(slot, cid, &g_cmd10);
 
+static int    mmcsd_recvblock(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
+                 int nbytes);
+#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY)
+static int    mmcsd_xmitblock(FAR struct mmcsd_slot_s *slot, const ubyte *buffer,
+                 int nbytes, ubyte token);
+#endif
+
 /* Block driver interfaces **************************************************/
 
 static int     mmcsd_open(FAR struct inode *inode);
@@ -233,38 +265,46 @@ static const uint32 g_transpeedtu[16] =
  * time from the end bit of the read command to start bit of the data block.
  *
  * The TAAC consists of a 3-bit time unit (TU) and a 4-bit time value (TV).
- * The access we need time is then given by:
+ * TAAC is in units of time; NSAC is in units of SPI clocks.
+ * The access time we need is then given by:
  *
- *   taccess = spifrequency / (TU*TV) + NAC
+ *   taccess = TU*TV + NSAC/spifrequency
  *
- * g_taactu holds the (1 / TU / 100 ) and g_taactv holds (100 / TV) so
- * that taccess can be computed without division.
+ * g_taactu holds TU in units of nanoseconds and microseconds (you have to use
+ * the index to distiguish.  g_taactv holds TV with 8-bits of fraction.
  */
 
-static const uint32 g_taactu[8] =
+#define MAX_USTUNDX 2
+static const uint16 g_taactu[8] =
 {
-  10000000, /* 0:   1 ns -> 1,000,000,000 Hz / 100 = 10,000,000 */
-   1000000, /* 1:  10 ns ->   100,000,000 Hz / 100 =  1,000,000 */
-    100000, /* 2: 100 ns ->    10,000,000 Hz / 100 =    100,000 */
-     10000, /* 3:   1 us ->     1,000,000 Hz / 100 =     10,000 */
-      1000, /* 4:  10 us ->       100,000 Hz / 100 =      1,000 */
-       100, /* 5: 100 us ->        10,000 Hz / 100 =        100 */
-        10, /* 6:   1 ms ->         1,000 Hz / 100 =         10 */
-         1, /* 7:  10 ms ->           100 Hz / 100 =          1 */
+/* Units of nanoseconds */
+
+      1, /* 0:   1 ns */
+     10, /* 1:  10 ns */
+    100, /* 2: 100 ns */
+
+/* Units of microseconds */
+
+      1, /* 3:   1 us 1,000 ns */
+     10, /* 4:  10 us 10,000 ns */
+    100, /* 5: 100 us 100,000 ns */
+   1000, /* 6:   1 ms 1,000,000 ns*/
+  10000, /* 7:  10 ms 10,000,000 ns */
 };
 
-static const uint32 g_taactv[] =
+static const uint16 g_taactv[] =
 {
-   0, 100,  83,  77, /*  0-3:  Reserved, 100/1.0, 100/1.2, 100/1.3 */
-  67,  50,  40,  33, /*  4-7:   100/1.5, 100/2.0, 100/2.5, 100/3.0 */
-  29,  25,  22,  20, /*  8-11:  100/3.5, 100/4.0, 100/4.5, 100/5.0 */
-  18,  17,  14,  13  /* 12-15:  100/5.5, 100/6.0, 100/7.0, 100/8.0 */
+  0x000,  0x100, 0x133, 0x14d, /*  0-3:  Reserved, 1.0, 1.2, 1.3 */
+  0x180,  0x200, 0x280, 0x300, /*  4-7:   1.5, 2.0, 2.5, 3.0 */
+  0x380,  0x400, 0x480, 0x500, /*  8-11:  3.5, 4.0, 4.5, 5.0 */
+  0x580,  0x600, 0x700, 0x800  /* 12-15:  5.5, 6.0, 7.0, 8.0 */
 };
 
 /* Commands *****************************************************************/
 
 static const struct mmcsd_cmdinfo_s g_cmd0   = {0x40, MMCSD_CMDARG_NONE,    MMCSD_CMDRESP_R1};
 static const struct mmcsd_cmdinfo_s g_cmd1   = {0x41, MMCSD_CMDARG_NONE,    MMCSD_CMDRESP_R1};
+static const struct mmcsd_cmdinfo_s g_cmd8   = {0x48, MMCSD_CMDARG_1AA,     MMCSD_CMDRESP_R7};
 static const struct mmcsd_cmdinfo_s g_cmd9   = {0x49, MMCSD_CMDARG_NONE,    MMCSD_CMDRESP_R1};
 static const struct mmcsd_cmdinfo_s g_cmd10  = {0x4a, MMCSD_CMDARG_NONE,    MMCSD_CMDRESP_R1};
 static const struct mmcsd_cmdinfo_s g_cmd12  = {0x4c, MMCSD_CMDARG_NONE,    MMCSD_CMDRESP_R1};
@@ -290,6 +330,7 @@ static const struct mmcsd_cmdinfo_s g_cmd55  = {0x77, MMCSD_CMDARG_NONE,    MMCS
 static const struct mmcsd_cmdinfo_s g_cmd56  = {0x78, MMCSD_CMDARG_NONE,    MMCSD_CMDRESP_R1};
 static const struct mmcsd_cmdinfo_s g_cmd58  = {0x7a, MMCSD_CMDARG_NONE,    MMCSD_CMDRESP_R3};
 static const struct mmcsd_cmdinfo_s g_cmd59  = {0x7b, MMCSD_CMDARG_DUMMY,   MMCSD_CMDRESP_R1};
+static const struct mmcsd_cmdinfo_s g_acmd23 = {0x69, MMCSD_CMDARG_NSECT,   MMCSD_CMDRESP_R1};
 static const struct mmcsd_cmdinfo_s g_acmd41 = {0x69, MMCSD_CMDARG_NONE,    MMCSD_CMDRESP_R1};
 
 /****************************************************************************
@@ -326,18 +367,22 @@ static int mmcsd_waitready(FAR struct mmcsd_slot_s *slot)
 {
   FAR struct spi_dev_s *spi = slot->spi;
   ubyte response;
-  int i;
+  uint32 start;
+  uint32 elapsed;
 
-  /* Wait until the card is no longer busy */
+  /* Wait until the card is no longer busy (up to 500MS) */
 
-  for (i = 0; i < slot->twrite; i++)
+  start = START_TIME;
+  do
     {
       response = SPI_SEND(spi, 0xff);
       if (response == 0xff)
         {
           return OK;
         }
+      elapsed = ELAPSED_TIME(start);
     }
+  while (elapsed < MMCSD_DELAY_500MS);
 
   fdbg("Card still busy, last response: %02x\n", response);
   return -EBUSY;
@@ -391,7 +436,11 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
 
   if (cmd->cmd == 0x40)
     {
-      SPI_SEND(spi, 0x95);
+      SPI_SEND(spi, 0x95);    /* CRC for CMD0 */
+    }
+  else if (cmd->cmd == 0x58)
+    {
+      SPI_SEND(spi, 0x87);    /* CRC for CMD8 */
     }
   else
     {
@@ -416,44 +465,80 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
 
   /* Interpret the response according to the command */
 
+  result = response;
   switch (cmd->resp)
     {
+    /* The R1B response is two bytes long */
+
     case MMCSD_CMDRESP_R1B:
       {
         uint32 busy = 0;
-        for (i = 0; i < slot->twrite && busy != 0xff; i++)
+        uint32 start;
+        uint32 elapsed;
+
+        start = START_TIME;
+        do
           {
             busy = SPI_SEND(spi, 0xff);
+            elapsed = ELAPSED_TIME(start);
           }
-        fvdbg("Return R1B=%02x\n", response);
+        while (elapsed < slot->twrite && busy != 0xff);
+
+        if (busy != 0xff)
+          {
+            fdbg("Failed: card still busy (%02x)\n", busy);
+            SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+            return (uint32)-1;
+          }
+
+        fvdbg("Return R1B=%04x\n", response);
       }
-      return (uint32)response;
+      break;
+
+    /* The R1 response is a single byte */
 
     case MMCSD_CMDRESP_R1:
       {
         fvdbg("Return R1=%02x\n", response);
       }
-      return (uint32)response;
+      break;
+
+    /* The R2 response is two bytes long */
 
     case MMCSD_CMDRESP_R2:
       {
-        result  = ((uint32) response << 8) & 0x0000ff00;
+        result  = ((uint32)(response & 0xff) << 8);
         result |= SPI_SEND(spi, 0xff) & 0xff;
         fvdbg("Return R2=%04x\n", result);
       }
-      return result;
+      break;
+
+    /* The R3 response is 5 bytes long */
 
     case MMCSD_CMDRESP_R3:
+      {
+        slot->ocr  = ((uint32)(response & 0xff) << 24);
+        slot->ocr |= ((uint32)(SPI_SEND(spi, 0xff) & 0xff) << 16);
+        slot->ocr |= ((uint32)(SPI_SEND(spi, 0xff) & 0xff) << 8);
+        slot->ocr |= SPI_SEND(spi, 0xff) & 0xff;
+        fvdbg("R1=%02x OCR=%08x\n", response, slot->ocr);
+      }
+
+    /* The R7 response is 5 bytes long */
+    case MMCSD_CMDRESP_R7:
     default:
       {
-        result  = ((uint32)response << 24) & 0xff000000;
-        result |= ((uint32)SPI_SEND(spi, 0xff) << 16) & 0x00ff0000;
-        result |= ((uint32)SPI_SEND(spi, 0xff) << 8) & 0x0000ff00;
-        result |= SPI_SEND(spi, 0xff) & 0xff;
-        fvdbg("Return R3=%08x\n", result);
+        slot->r7  = ((uint32)(response & 0xff) << 24);
+        slot->r7 |= ((uint32)(SPI_SEND(spi, 0xff) & 0xff) << 16);
+        slot->r7 |= ((uint32)(SPI_SEND(spi, 0xff) & 0xff) << 8);
+        slot->r7 |= SPI_SEND(spi, 0xff) & 0xff;
+        fvdbg("R1=%08x R7=%08x\n", response, slot->r7);
       }
-      return result;
+      break;
     }
+
+  SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+  return result;
 }
 
 /****************************************************************************
@@ -469,10 +554,67 @@ static void mmcsd_setblklen(FAR struct mmcsd_slot_s *slot, uint32 length)
   FAR struct spi_dev_s *spi = slot->spi;
   uint32 result;
 
+  SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
   result = mmcsd_sendcmd(slot, &g_cmd16, length);
   SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
 }
 
+/****************************************************************************
+ * Name: mmcsd_nsac
+ *
+ * Description: Convert the value of the NSAC to millisconds
+ *
+ ****************************************************************************/
+
+static uint32 mmcsd_nsac(FAR struct mmcsd_slot_s *slot, ubyte *csd, uint32 frequency)
+{
+  /* NSAC is 8-bits width and is in units of 100 clock cycles.  Therefore, the
+   * maximum value is 25.5K clock cycles.
+   */
+
+  uint32 nsac = MMCSD_CSD_NSAC(csd) * 100000;
+  return (nsac + (frequency >> 1)) / frequency;
+}
+
+/****************************************************************************
+ * Name: mmcsd_taac
+ *
+ * Description: Convert the value of the TAAC to millisconds
+ *
+ ****************************************************************************/
+
+static uint32 mmcsd_taac(FAR struct mmcsd_slot_s *slot, ubyte *csd)
+{
+  int tundx;
+
+  /*The TAAC consists of a 3-bit time unit (TU) and a 4-bit time value (TV).
+   * TAAC is in units of time; NSAC is in units of SPI clocks.
+   * The access time we need is then given by:
+   *
+   *   taccess = TU*TV + NSAC/spifrequency
+   *
+   * g_taactu holds TU in units of nanoseconds and microseconds (you have to use
+   * the index to distiguish.  g_taactv holds TV with 8-bits of fraction.
+   */
+
+  tundx  = MMCSD_CSD_TAAC_TIMEUNIT(csd);
+  if (tundx <= MAX_USTUNDX)
+    {
+      /* The maximum value of the nanosecond TAAC is 800 ns. The rounded
+       * answer in milliseconds will always be zero.
+       */
+
+      return 0;
+    }
+  else
+    {
+      /* Return the answer in milliseconds */
+
+      uint32 taacus = (g_taactu[tundx]*g_taactv[MMCSD_CSD_TAAC_TIMEVALUE(csd)] + 0x80) >> 8;
+      return (taacus + 500) / 1000;
+    }
+}
+
 /****************************************************************************
  * Name: mmcsd_decodecsd
  *
@@ -484,6 +626,9 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd)
 {
   FAR struct spi_dev_s *spi = slot->spi;
   uint32 frequency;
+  uint32 readbllen;
+  uint32 csizemult;
+  uint32 csize;
 
   /* Calculate SPI max clock */
 
@@ -491,32 +636,48 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd)
     g_transpeedtu[MMCSD_CSD_TRANSPEED_TIMEVALUE(csd)] *
     g_transpeedru[MMCSD_CSD_TRANSPEED_TRANSFERRATEUNIT(csd)];
 
-  if (frequency > 20000000)
+  if (frequency > CONFIG_MMCSD_SPICLOCK)
     {
-      frequency = 20000000;
+      frequency = CONFIG_MMCSD_SPICLOCK;
     }
 
   /* Set the SPI frequency to that value */
 
   frequency = SPI_SETFREQUENCY(spi, frequency);
 
-  /* Now determine the delay to */
+  /* Now determine the delay to access data */
 
   if (slot->type == MMCSD_CARDTYPE_MMC)
     {
-      slot->taccess =
-        g_taactu[MMCSD_CSD_TAAC_TIMEUNIT(csd)] *
-        g_taactv[MMCSD_CSD_TAAC_TIMEVALUE(csd)];
+      /* The TAAC consists of a 3-bit time unit (TU) and a 4-bit time value (TV).
+       * TAAC is in units of time; NSAC is in units of SPI clocks.
+       * The access time we need is then given by:
+       *
+       *   taccess = TU*TV + NSAC/spifrequency
+       *
+       * First get the access time in milliseconds.
+       */
+
+      uint32 taccessms = mmcsd_taac(slot, csd) + mmcsd_nsac(slot, csd, frequency);
+
+      /* Then convert to system clock ticks.  The maximum read access is 10 * the
+       * tacc value: taccess = 10 * taccessms / CLK_TCK / 1000, or
+       */
+
+      slot->taccess = taccessms / CLK_TCK / 100 + 1;
 
-      slot->taccess  = frequency / slot->taccess;
-      slot->taccess += 1 << (MMCSD_CSD_NSAC(csd) + 4);
-      slot->taccess *= 10;
-      slot->twrite   = slot->taccess * MMCSD_CSD_R2WFACTOR(csd);
+      /* The write access time is larger by the R2WFACTOR */
+
+      slot->twrite = taccessms * MMCSD_CSD_R2WFACTOR(csd) / CLK_TCK / 100 + 1;
     }
   else
     {
-      slot->taccess  = frequency / SD_READACCESSHZ;
-      slot->twrite   = frequency / SD_WRITEACCESSHZ;
+      /* For SD, the average is still given by the TAAC+NSAC, but the
+       * maximum are the constants 100 and 250MS
+       */
+
+      slot->taccess  = SD_READACCESS;
+      slot->twrite   = SD_WRITEACCESS;
     }
 
   fvdbg("Frequency:         %d\n", frequency);
@@ -526,10 +687,10 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd)
   /* Get the physical geometry of the card: sector size and number of
    * sectors. The card's total capacity is computed from
    *
-   *   capacity = BLOCKNR * BLOCK_LEN
-   *   BLOCKNR = (C_SIZE+1)*MULT
-   *   MULT = 2**(C_SIZE_MULT+2)         (C_SIZE_MULT < 8)
-   *   BLOCK_LEN = 2**READD_BL_LEN       (READ_BL_LEN < 12)
+   *   capacity  = BLOCKNR * BLOCK_LEN
+   *   BLOCKNR   = (C_SIZE+1)*MULT
+   *   MULT      = 2**(C_SIZE_MULT+2)    (C_SIZE_MULT < 8)
+   *   BLOCK_LEN = 2**READ_BL_LEN        (READ_BL_LEN < 12)
    *
    * Or
    *
@@ -540,39 +701,39 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd)
    *   nsectors = ((C_SIZE+1) << (C_SIZE_MULT + 2))
    */
 
-  if (MMCSD_CSD_CSDSTRUCT(csd) == 1)
+  if (MMCSD_CSD_CSDSTRUCT(csd) != 0)
     {
-      /* SDC ver 2.00 */
+      /* SDC structure ver 2.xx */
       /* Note: On SD card WRITE_BL_LEN is always the same as READ_BL_LEN */
 
-      int readbllen = SD20_CSD_READBLLEN(csd);
-      int csizemult = (SD20_CSD_CSIZEMULT(csd) + 2);
+      readbllen = SD20_CSD_READBLLEN(csd);
+      csizemult = SD20_CSD_CSIZEMULT(csd) + 2;
+      csize     = SD20_CSD_CSIZE(csd) + 1;
+    }
+  else
+    {
+      /* MMC or SD structure ver 1.xx */
+      /* Note: On SD card WRITE_BL_LEN is always the same as READ_BL_LEN */
 
-      /* "To make 2 GByte card, the Maximum Block Length (READ_BL_LEN=WRITE_BL_LEN)
-       *  shall be set to 1024 bytes. However, the Block Length, set by CMD16, shall
-       *  be up to 512 bytes to keep consistency with 512 bytes Maximum Block Length
-       *  cards (Less than and equal 2 Gbyte cards)."
-       */
-#if 0
+      readbllen = MMCSD_CSD_READBLLEN(csd);
+      csizemult = MMCSD_CSD_CSIZEMULT(csd) + 2;
+      csize     = MMCSD_CSD_CSIZE(csd) + 1;
+    }
+
+  /* SDHC cards have fixed sector size of 512 bytes */
+
+  if (IS_SDV2(slot->type))
+    {
       if (readbllen > 9)
         {
           fdbg("Forcing 512 byte sector size\n");
           csizemult   += (readbllen - 9);
           readbllen    = 9;
         }
-#endif
-      slot->sectorsize = 1 << readbllen;
-      slot->nsectors   = (SD20_CSD_CSIZE(csd) + 1) << csizemult;
-    }
-  else
-    {
-      /* MMC or SD ver 1.xx */
-      /* Note: On SD card WRITE_BL_LEN is always the same as READ_BL_LEN */
-
-      slot->sectorsize = 1 << MMCSD_CSD_READBLLEN(csd);
-      slot->nsectors = (MMCSD_CSD_CSIZE(csd) + 1) << (MMCSD_CSD_CSIZEMULT(csd) + 2);
     }
 
+  slot->sectorsize = 1 << readbllen;
+  slot->nsectors   = csize << csizemult;
   fvdbg("Sector size:       %d\n", slot->sectorsize);
   fvdbg("Number of sectors: %d\n", slot->nsectors);
 }
@@ -580,7 +741,7 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd)
 /****************************************************************************
  * Name: mmcsd_checkwrprotect
  *
- * Description: 
+ * Description:
  *
  ****************************************************************************/
 
@@ -621,7 +782,7 @@ static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
   ubyte response;
   int i;
 
-  SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+  SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
   SPI_SEND(spi, 0xff);
 
   /* Send the CMD9 or CMD10 */
@@ -671,6 +832,95 @@ errout_with_eio:
   return -EIO;
 }
 
+/****************************************************************************
+ * Name: mmcsd_recvblock
+ *
+ * Description:  Receive a data block from the card
+ *
+ ****************************************************************************/
+
+static int mmcsd_recvblock(FAR struct mmcsd_slot_s *slot, ubyte *buffer, int nbytes)
+{
+  FAR struct spi_dev_s *spi = slot->spi;
+  uint32 start;
+  uint32 elapsed;
+  ubyte  token;
+
+  /* Wait up to the maximum to receive a valid data token.  taccess is the
+   * time from when the command is sent until the first byte of data is
+   * received */
+
+  start = START_TIME;
+  do
+    {
+      token = SPI_SEND(spi, 0xff);
+      elapsed = ELAPSED_TIME(start);
+    }
+  while (token == 0xff && elapsed < slot->taccess);
+
+  if (token == MMCSD_SPIDT_STARTBLKSNGL)
+    {
+      /* Receive the block */
+
+      SPI_RECVBLOCK(spi, buffer, nbytes);
+
+      /* Discard the CRC */
+
+      SPI_SEND(spi, 0xff);
+      SPI_SEND(spi, 0xff);
+      return OK;
+    }
+
+  fdbg("Did not received data token (%02x)\n", token);
+  return ERROR;
+}
+
+/****************************************************************************
+ * Name: mmcsd_xmitblock
+ *
+ * Description:  Transmit a data block to the card
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_FS_WRITABLE) && !defined(CONFIG_MMCSD_READONLY)
+static int mmcsd_xmitblock(FAR struct mmcsd_slot_s *slot, const ubyte *buffer,
+                           int nbytes, ubyte token)
+{
+  FAR struct spi_dev_s *spi = slot->spi;
+  ubyte response;
+
+  /* Start the block transfer:
+   * 1. 0xff (sync)
+   * 2. 0xfe or 0xfc (start of block token)
+   * 3. Followed by the block of data and 2 byte CRC
+   */
+
+  SPI_SEND(spi, 0xff);                     /* sync */
+  SPI_SEND(spi, token);                    /* data token */
+
+  /* Transmit the block to the MMC/SD card */
+
+  (void)SPI_SNDBLOCK(spi, buffer, nbytes);
+
+  /* Add the bogus CRC.  By default, the SPI interface is initialized in
+   * non-protected mode.  However, we still have to send bogus CRC values
+   */
+
+  SPI_SEND(spi, 0xff);
+  SPI_SEND(spi, 0xff);
+
+  /* Now get the data response */
+
+  response = SPI_SEND(spi, 0xff);
+  if ((response & MMCSD_SPIDR_MASK) != MMCSD_SPIDR_ACCEPTED)
+    {
+      fdbg("Bad data response: %02x\n", response);
+      return -EIO;
+    }
+  return OK;
+}
+#endif /* CONFIG_FS_WRITABLE && !CONFIG_MMCSD_READONLY */
+
 /****************************************************************************
  * Block Driver Operations
  ****************************************************************************/
@@ -714,7 +964,7 @@ static int mmcsd_open(FAR struct inode *inode)
   /* Select the slave */
 
   mmcsd_semtake(&slot->sem);
-  SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+  SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
 
   /* Verify that the MMC/SD card is alive and ready for business */
 
@@ -751,8 +1001,8 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
   FAR struct spi_dev_s *spi;
   size_t nbytes;
   off_t  offset;
-  ubyte response;
-  int i;
+  ubyte  response;
+  int    i;
 
   fvdbg("start_sector=%d nsectors=%d\n", start_sector, nsectors);
 
@@ -801,66 +1051,85 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
   /* Convert sector and nsectors to nbytes and byte offset */
 
   nbytes = nsectors * slot->sectorsize;
-  offset = start_sector * slot->sectorsize;
-  fvdbg("nbytes=%d offset=%d\n", nbytes, offset);
+  if (IS_BLOCK(slot->type))
+    {
+      offset = start_sector;
+      fvdbg("nbytes=%d sector offset=%d\n", nbytes, offset);
+    }
+  else
+    {
+      offset = start_sector * slot->sectorsize;
+      fvdbg("nbytes=%d byte offset=%d\n", nbytes, offset);
+    }
 
   /* Select the slave and synchronize */
 
   mmcsd_semtake(&slot->sem);
-  SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+  SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
   SPI_SEND(spi, 0xff);
 
-  /* Send CMD17: Reads a block of the size selected by the SET_BLOCKLEN
-   * command and verify that good R1 status is returned
-   */
+  /* Single or multiple block read? */
 
-  response = mmcsd_sendcmd(slot, &g_cmd17, offset);
-  if (response != MMCSD_SPIR1_OK)
+  if (nsectors == 1)
     {
-      fdbg("CMD17 failed: R1=%02x\n", response);
-      goto errout_with_eio;
-    }
-
-  /* Loop only for the computed timeout */
+      /* Send CMD17: Reads a block of the size selected by the SET_BLOCKLEN
+       * command and verify that good R1 status is returned
+       */
 
-  for (i = 0; i < slot->taccess; i++)
-    {
-      /* Synchronize */
+      response = mmcsd_sendcmd(slot, &g_cmd17, offset);
+      if (response != MMCSD_SPIR1_OK)
+        {
+          fdbg("CMD17 failed: R1=%02x\n", response);
+          goto errout_with_eio;
+        }
 
-      response = SPI_SEND(spi, 0xff);
-      fvdbg("(%d) SPI send returned %02x\n", i, response);
+      /* Receive the block */
 
-      /* If a read operation fails and the card cannot provide the requested
-       * data, it will send a data error token instead.  The 4 least
-       * significant bits are the same as those in the R2 response.
+      if (mmcsd_recvblock(slot, buffer, slot->sectorsize) != 0)
+        {
+          fdbg("Failed: to receive the block\n");
+          goto errout_with_eio;
+        }
+    }
+  else
+    {
+      /* Send CMD17: Reads a block of the size selected by the SET_BLOCKLEN
+       * command and verify that good R1 status is returned
        */
 
-      if (response != 0 && (response & MMCSD_SPIDET_UPPER) == 0)
+      response = mmcsd_sendcmd(slot, &g_cmd18, offset);
+      if (response != MMCSD_SPIR1_OK)
         {
-          fdbg("(%d) Data transfer error: %02x\n", i, response);
+          fdbg("CMD118 failed: R1=%02x\n", response);
           goto errout_with_eio;
         }
-      else if (response == MMCSD_SPIDT_STARTBLKSNGL)
-        {
-          /* Receive the block of data */
 
-          SPI_RECVBLOCK(spi, buffer, nbytes);
+      /* Receive each block */
 
-          /* Receive and ignore the two CRC bytes */
+      for (i = 0; i < nsectors; i++)
+        {
+          if (mmcsd_recvblock(slot, buffer, slot->sectorsize) != 0)
+            {
+              fdbg("Failed: to receive the block\n");
+              goto errout_with_eio;
+            }
+         buffer += slot->sectorsize;
+       }
 
-          SPI_SEND(spi, 0xff);
-          SPI_SEND(spi, 0xff);
+      /* Send CMD12: Stops transmission */
 
-          /* On success, return the number of sectors transfer */
+      response = mmcsd_sendcmd(slot, &g_cmd12, 0);
+    }
 
-          SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
-          mmcsd_semgive(&slot->sem);
+  /* On success, return the number of sectors transfer */
 
-          fvdbg("(%d) Read %d bytes:\n", i, nbytes);
-          mmcsd_dumpbuffer(buffer, nbytes);
-          return nsectors;
-        }
-    }
+  SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+  SPI_SEND(spi, 0xff);
+  mmcsd_semgive(&slot->sem);
+
+  fvdbg("(%d) Read %d bytes:\n", elapsed, nbytes);
+  mmcsd_dumpbuffer(buffer, nbytes);
+  return nsectors;
 
 errout_with_eio:
   SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
@@ -886,6 +1155,7 @@ static ssize_t mmcsd_write(FAR struct inode *inode, const unsigned char *buffer,
   off_t  offset;
   ubyte response;
   int ret;
+  int i;
 
   fvdbg("start_sector=%d nsectors=%d\n", start_sector, nsectors);
 
@@ -942,74 +1212,102 @@ static ssize_t mmcsd_write(FAR struct inode *inode, const unsigned char *buffer,
   /* Convert sector and nsectors to nbytes and byte offset */
 
   nbytes = nsectors * slot->sectorsize;
-  offset = start_sector * slot->sectorsize;
-  fvdbg("Writing %d bytes to offset %d:\n", nbytes, offset);
+  if (IS_BLOCK(slot->type))
+    {
+      offset = start_sector;
+      fvdbg("nbytes=%d sector offset=%d\n", nbytes, offset);
+    }
+  else
+    {
+      offset = start_sector * slot->sectorsize;
+      fvdbg("nbytes=%d byte offset=%d\n", nbytes, offset);
+    }
   mmcsd_dumpbuffer(buffer, nbytes);
 
   /* Select the slave and synchronize */
 
   mmcsd_semtake(&slot->sem);
-  SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+  SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
   SPI_SEND(spi, 0xff);
 
-  /* Send CMD24 (WRITE_BLOCK) and verify that good R1 status is returned */
+  /* Single or multiple block transfer? */
 
-  response = mmcsd_sendcmd(slot, &g_cmd24, offset);
-  if (response != MMCSD_SPIR1_OK)
+  if (nsectors == 1)
     {
-      fdbg("CMD24 failed: R1=%02x\n", response);
-      SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
-      ret = -EIO;
-      goto errout_with_sem;
+      /* Send CMD24 (WRITE_BLOCK) and verify that good R1 status is returned */
+
+      response = mmcsd_sendcmd(slot, &g_cmd24, offset);
+      if (response != MMCSD_SPIR1_OK)
+        {
+          fdbg("CMD24 failed: R1=%02x\n", response);
+          goto errout_with_sem;
+        }
+
+      /* Then transfer the sector */
+
+      if (mmcsd_xmitblock(slot, buffer, slot->sectorsize, 0xfe) != 0)
+        {
+          fdbg("Block transfer failed\n");
+          goto errout_with_sem;
+        }
     }
+  else
+    {
+      /* Set the number of blocks to be pre-erased (SD only) */
 
-  /* Start the block transfer:
-   * 1. 0xff (sync)
-   * 2. 0xfe (start of block)
-   * 3. Followed by the block of data
-   */
+      if (IS_SD(slot->type))
+        {
+          response = mmcsd_sendcmd(slot, &g_acmd23, nsectors);
+          if (response != MMCSD_SPIR1_OK)
+            {
+              fdbg("ACMD23 failed: R1=%02x\n", response);
+              goto errout_with_sem;
+            }
+       }
 
-  SPI_SEND(spi, 0xff);
-  SPI_SEND(spi, MMCSD_SPIDT_STARTBLKSNGL);
-  (void)SPI_SNDBLOCK(spi, buffer, nbytes);
+      /* Send CMD25:  Continuously write blocks of data until the
+       * tranmission is stopped.
+       */
 
-  /* Add the bogus CRC.  By default, the SPI interface is initialized in
-   * non-protected mode.  However, we still have to send bogus CRC values
-   */
+      response = mmcsd_sendcmd(slot, &g_cmd25, offset);
+      if (response != MMCSD_SPIR1_OK)
+        {
+          fdbg("CMD25 failed: R1=%02x\n", response);
+          goto errout_with_sem;
+        }
 
-  SPI_SEND(spi, 0xff);
-  SPI_SEND(spi, 0xff);
+      /* Transmit each block */
 
-  /* Now get the data response */
+      for (i = 0; i < nsectors; i++)
+        {
+          if (mmcsd_xmitblock(slot, buffer, slot->sectorsize, 0xfc) != 0)
+            {
+              fdbg("Failed: to receive the block\n");
+              goto errout_with_sem;
+            }
+          buffer += slot->sectorsize;
+        }
 
-  response = SPI_SEND(spi, 0xff);
-  if ((response & MMCSD_SPIDR_MASK) != MMCSD_SPIDR_ACCEPTED)
-    {
-      fdbg("Bad data response: %02x\n", response);
-      ret = -EIO;
-      goto errout_with_sem;
+      /* Send the stop transmission token */
+
+      SPI_SEND(spi, MMCSD_SPIDT_STOPTRANS);
     }
 
   /* Wait until the card is no longer busy */
 
   ret = mmcsd_waitready(slot);
   SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+  SPI_SEND(spi, 0xff);
   mmcsd_semgive(&slot->sem);
 
-  /* Verify that the card successfully became non-busy */
-
-  if (ret < 0)
-    {
-      return ret;
-    }
-
   /* The success return value is the number of sectors written */
 
   return nsectors;
 
 errout_with_sem:
+  SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
   mmcsd_semgive(&slot->sem);
-  return ret;
+  return -EIO;
 }
 #endif
 
@@ -1118,6 +1416,8 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
   FAR struct spi_dev_s *spi = slot->spi;
   ubyte csd[16];
   uint32 result = MMCSD_SPIR1_IDLESTATE;
+  uint32 start;
+  uint32 elapsed;
   int i, j;
 
   /* Assume that the card is not ready (we'll clear this on successful car
@@ -1145,7 +1445,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
 
   /* Set the maximum access time out */
 
-  slot->taccess = MMCSD_IDMODE_CLOCK / SD_READACCESSHZ;
+  slot->taccess = SD_READACCESS;
 
   /* The SD card wakes up in SD mode. It will enter SPI mode if the chip select signal is
    * asserted (negative) during the reception of the reset command (CMD0) and the card is in
@@ -1157,7 +1457,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
   fvdbg("Send CMD0\n");
   for (i = 0; i < 2; i++)
     {
-      SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+      SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
 
       for (j = 10; j; j--)
         {
@@ -1186,62 +1486,141 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
       return -EIO;
     }
 
-  /* Determinate Card type SD or MMC */
+  slot->type = MMCSD_CARDTYPE_UNKNOWN;
 
-  slot->type = MMCSD_CARDTYPE_MMC;
+  /* Check for SDHC Version 2.x.  CMD 8 is reserved on SD version 1.0 and MMC. */
 
-  for (i = 100; i; --i)
+  fvdbg("Send CMD8\n");
+  SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
+  SPI_SEND(spi, 0xff);
+  result = mmcsd_sendcmd(slot, &g_cmd8, 0x1aa);
+
+  if (result == MMCSD_SPIR1_IDLESTATE)
     {
-      fvdbg("%d. Send CMD55\n", i);
-      SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+      /* Should also check the operating voltage here */
+
+      if ((slot->r7 & MMCSD_SPIR7_ECHO_MASK) == 0xaa)
+        {
+          /* Try CMD55/ACMD41 up to 100 times */
+
+          start   = START_TIME;
+          elapsed = 0;
+          do
+            {
+              fvdbg("%d. Send CMD55\n", i);
+              SPI_SEND(spi, 0xff);
+              result = mmcsd_sendcmd(slot, &g_cmd55, 0);
+              if (result == MMCSD_SPIR1_IDLESTATE || result == MMCSD_SPIR1_OK)
+                {
+                  fvdbg("%d. Send ACMD41\n", i);
+                  SPI_SEND(spi, 0xff);
+                  result = mmcsd_sendcmd(slot, &g_acmd41, 1 << 30);
+                  if (result == MMCSD_SPIR1_OK)
+                    {
+                      break;
+                    }
+                }
+              elapsed = ELAPSED_TIME(start);
+            }
+          while (elapsed < MMCSD_DELAY_1SEC);
+
+          /* Check if ACMD41 was sent successfully */
+
+          if (elapsed < MMCSD_DELAY_1SEC)
+           {
+             fvdbg("Send CMD58\n");
+             SPI_SEND(spi, 0xff);
+             result = mmcsd_sendcmd(slot, &g_cmd58, 0);
+             if (result == MMCSD_SPIR1_OK)
+               {
+                  fvdbg("OCR: %08x\n", slot->ocr);
+                  if ((slot->ocr & MMCSD_OCR_CCS) != 0)
+                    {
+                      fdbg("Identified SD ver2 card/with block access\n");
+                      slot->type = MMCSD_CARDTYPE_SDV2|MMCSD_CARDTYPE_BLOCK;
+                    }
+                  else
+                    {
+                      fdbg("Identified SD ver2 card\n");
+                      slot->type = MMCSD_CARDTYPE_SDV2;
+                    }
+               }
+           }
+        }
+    }
+
+  /* Check for SDC version 1.x or MMC */
+
+  else
+    {
+      /* Both the MMC card and the SD card support CMD55 */
+
+      fvdbg("Send CMD55\n");
       SPI_SEND(spi, 0xff);
       result = mmcsd_sendcmd(slot, &g_cmd55, 0);
-      SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+      if (result == MMCSD_SPIR1_IDLESTATE || result == MMCSD_SPIR1_OK)
+        {
+          /* But ACMD41 is supported only on SD */
 
-      fvdbg("%d. Send ACMD41\n", i);
-      SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
-      SPI_SEND(spi, 0xff);
-      result = mmcsd_sendcmd(slot, &g_acmd41, 0);
-      SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+          fvdbg("Send ACMD41\n");
+          SPI_SEND(spi, 0xff);
+          result = mmcsd_sendcmd(slot, &g_acmd41, 0);
+          if (result == MMCSD_SPIR1_IDLESTATE || result == MMCSD_SPIR1_OK)
+            {
+              fdbg("Identified SD ver1 card\n");
+              slot->type = MMCSD_CARDTYPE_SDV1;
+            }
+        }
 
-      /* If this is an MMC card, it will response with ILLEGAL COMMAND */
+      /* Make sure that we are out of the Idle state */
 
-      if (result & MMCSD_SPIR1_ILLEGALCMD)
+      start   = START_TIME;
+      elapsed = 0;
+      do
         {
-          /* MMC card may be CMD1 for MMC Init sequence will be complete within 
-           * 500ms */
-
-          for (i = 100; i; --i)
+          if (IS_SD(slot->type))
+            {
+              fvdbg("%d. Send CMD55\n", i);
+              result = mmcsd_sendcmd(slot, &g_cmd55, 0);
+              if (result == MMCSD_SPIR1_IDLESTATE || result == MMCSD_SPIR1_OK)
+                {
+                  fvdbg("%d. Send ACMD41\n", i);
+                  SPI_SEND(spi, 0xff);
+                  result = mmcsd_sendcmd(slot, &g_acmd41, 0);
+                  if (result == MMCSD_SPIR1_OK)
+                    {
+                       break;
+                    }
+                }
+            }
+          else
             {
               fvdbg("%d. Send CMD1\n", i);
-              SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
               SPI_SEND(spi, 0xff);
               result = mmcsd_sendcmd(slot, &g_cmd1, 0);
-              SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
-
               if (result == MMCSD_SPIR1_OK)
                 {
-                  fvdbg("%d. Identified MMC card\n", i);
-                  slot->type = MMCSD_CARDTYPE_MMC;
-                  break;
+                   fdbg("%d. Identified MMC card\n", i);
+                   slot->type = MMCSD_CARDTYPE_MMC;
+                   break;
                 }
-              up_mdelay(50);
-            }
-          break;
+             }
+          elapsed = ELAPSED_TIME(start);
         }
-      else if (result == MMCSD_SPIR1_OK)
+      while (elapsed < MMCSD_DELAY_1SEC);
+
+      if (elapsed >= MMCSD_DELAY_1SEC)
         {
-          fvdbg("%d. Identified SD card\n", i);
-          slot->type = MMCSD_CARDTYPE_SD;
-          break;
+          fdbg("Failed to exit IDLE state\n");
+          SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
+          return -EIO;
         }
-
-      up_mdelay(50);
     }
 
-  if (i == 0)
+  if (slot->type == MMCSD_CARDTYPE_UNKNOWN)
     {
-      fdbg("Retry exhausted\n");
+      fdbg("Failed to identify card\n");
+      SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
       return -EIO;
     }
 
@@ -1252,31 +1631,25 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
   if (result != OK)
     {
       fdbg("mmcsd_getcsd(CMD9) failed: %d\n", result);
+      SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
       return -EIO;
     }
-
-#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_FS)
-  if (slot->type == MMCSD_CARDTYPE_MMC)
-    {
-      fdbg("Found MMC card\n");
-    }
-  else if (MMCSD_CSD_CSDSTRUCT(csd) == 1)
-    {
-      fdbg("Found SDHC card\n");
-    }
-  else
-    {
-      fdbg("Found SD card\n");
-    }
   mmcsd_dmpcsd(csd, slot->type);
-#endif
 
   /* CSD data and set block size */
 
   mmcsd_decodecsd(slot, csd);
   mmcsd_checkwrprotect(slot, csd);
-  mmcsd_setblklen(slot, slot->sectorsize);
+
+  /* SD Version block length is always 512 */
+
+  if (!IS_SDV2(slot->type))
+    {
+      mmcsd_setblklen(slot, slot->sectorsize);
+    }
+
   slot->state &= ~MMCSD_SLOTSTATUS_NOTREADY;
+  SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
   return OK;
 }
 
diff --git a/drivers/mmcsd/mmcsd_spi.h b/drivers/mmcsd/mmcsd_spi.h
index dea902446f2b41f1588a7931975e556316d6327d..7ad59aee1dd6bdf95378cef3dec1eb48cc7f4706 100644
--- a/drivers/mmcsd/mmcsd_spi.h
+++ b/drivers/mmcsd/mmcsd_spi.h
@@ -79,6 +79,15 @@
 #define MMCSD_SPIR2_ADDRERROR     0x2000 /* Address error */
 #define MMCSD_SPIR2_PARAMERROR    0x4000 /* Parameter error */
 
+/* Last 4 bytes of the 5 byte R7 response */
+
+#define MMCSD_SPIR7_VERSION_SHIFT 28     /* Bits 28-31: Command version number */
+#define MMCSD_SPIR7_VERSION_MASK  (0x0f << MMCSD_SPIR7_VERSION_SHIFT)
+#define MMCSD_SPIR7_VOLTAGE_SHIFT 8      /* Bits 8-11: Voltage accepted */
+#define MMCSD_SPIR7_VOLTAGE_MASK  (0x0f << MMCSD_SPIR7_VOLTAGE_SHIFT)
+#define MMCSD_SPIR7_ECHO_SHIFT    0      /* Bits 0-7: Echoed check pattern */
+#define MMCSD_SPIR7_ECHO_MASK     (0x0f << MMCSD_SPIR7_ECHO_SHIFT)
+
 /* Data Response */
 
 #define MMCSD_SPIDR_MASK          0x1f   /* Mask for valid data response bits */
@@ -100,6 +109,20 @@
 #define MMCSD_SPIDET_CARDECCFAIL  0x04   /* Card ECC failed */
 #define MMCSD_SPIDET_OUTOFRANGE   0x08   /* Out of range */
 
+/* Operating Conditions register */
+
+#define MMCSD_OCR_V27             (1 << 15) /* Bit 15: 2.7-2.8V */
+#define MMCSD_OCR_V28             (1 << 16) /* Bit 16: 2.8-2.9V */
+#define MMCSD_OCR_V29             (1 << 17) /* Bit 17: 2.9-3.0V */
+#define MMCSD_OCR_V30             (1 << 18) /* Bit 18: 3.0-3.1V */
+#define MMCSD_OCR_V31             (1 << 19) /* Bit 19: 3.1-3.2V */
+#define MMCSD_OCR_V32             (1 << 20) /* Bit 20: 3.2-3.3V */
+#define MMCSD_OCR_V33             (1 << 21) /* Bit 21: 3.3-3.4V */
+#define MMCSD_OCR_V34             (1 << 22) /* Bit 22: 3.4-3.5V */
+#define MMCSD_OCR_V35             (1 << 23) /* Bit 23: 3.5-3.6V */
+#define MMCSD_OCR_CCS             (1 << 30) /* Bit 30: Card capacity status */
+#define MMCSD_OCR_BUSY            (1 << 31) /* Bit 31: Card powered up status bit */
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/