Integrating new MMC/SD design

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1827 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2009-05-26 23:45:45 +00:00
parent d68f3bc37a
commit e832c2ac9b
3 changed files with 144 additions and 100 deletions
+10 -6
View File
@@ -59,23 +59,27 @@
* Definitions * Definitions
************************************************************************************/ ************************************************************************************/
/* Enables debug output from this file (needs CONFIG_DEBUG with CONFIG_DEBUG_VERBOSE /* Enables debug output from this file (needs CONFIG_DEBUG too) */
* too)
*/
#undef SSI_DEBUG /* Define to enable debug */ #undef SSI_DEBUG /* Define to enable debug */
#undef SSI_VERBOSE /* Define to enable verbose debug */
#ifdef SSI_DEBUG #ifdef SSI_DEBUG
# define ssidbg lldbg # define ssidbg lldbg
# define ssivdbg llvdbg # ifdef SSI_VERBOSE
# define ssivdbg lldbg
# else
# define ssivdbg(x...)
# endif
#else #else
# undef SSI_VERBOSE
# define ssidbg(x...) # define ssidbg(x...)
# define ssivdbg(x...) # define ssivdbg(x...)
#endif #endif
/* Dump GPIO registers */ /* Dump GPIO registers */
#ifdef SSI_DEBUG #ifdef SSI_VERBOSE
# define ssi_dumpgpio(m) lm3s_dumpgpio(SDCCS_GPIO, m) # define ssi_dumpgpio(m) lm3s_dumpgpio(SDCCS_GPIO, m)
#else #else
# define ssi_dumpgpio(m) # define ssi_dumpgpio(m)
+92 -93
View File
@@ -38,7 +38,6 @@
****************************************************************************/ ****************************************************************************/
#include <nuttx/config.h> #include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdio.h> #include <stdio.h>
@@ -153,6 +152,7 @@ struct mmcsd_cmdinfo_s
ubyte cmd; ubyte cmd;
ubyte arg; ubyte arg;
ubyte resp; ubyte resp;
ubyte chksum;
}; };
/**************************************************************************** /****************************************************************************
@@ -271,7 +271,7 @@ static const uint32 g_transpeedtu[16] =
* taccess = TU*TV + NSAC/spifrequency * taccess = TU*TV + NSAC/spifrequency
* *
* g_taactu holds TU in units of nanoseconds and microseconds (you have to use * 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. * the index to distiguish). g_taactv holds TV with 8-bits of fraction.
*/ */
#define MAX_USTUNDX 2 #define MAX_USTUNDX 2
@@ -302,36 +302,21 @@ static const uint16 g_taactv[] =
/* Commands *****************************************************************/ /* Commands *****************************************************************/
static const struct mmcsd_cmdinfo_s g_cmd0 = {0x40, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd0 = {CMD0, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1, 0x95};
static const struct mmcsd_cmdinfo_s g_cmd1 = {0x41, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd1 = {CMD1, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd8 = {0x48, MMCSD_CMDARG_1AA, MMCSD_CMDRESP_R7}; static const struct mmcsd_cmdinfo_s g_cmd8 = {CMD8, MMCSD_CMDARG_1AA, MMCSD_CMDRESP_R7, 0x87};
static const struct mmcsd_cmdinfo_s g_cmd9 = {0x49, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd9 = {CMD9, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd10 = {0x4a, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd10 = {CMD10, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd12 = {0x4c, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd12 = {CMD12, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd13 = {0x4d, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R2}; static const struct mmcsd_cmdinfo_s g_cmd16 = {CMD16, MMCSD_CMDARG_BLKLEN, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd16 = {0x50, MMCSD_CMDARG_BLKLEN, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd17 = {CMD17, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd17 = {0x51, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd18 = {CMD18, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd18 = {0x52, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd24 = {CMD24, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd24 = {0x58, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd25 = {CMD25, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd25 = {0x59, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd55 = {CMD55, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd27 = {0x5b, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1}; static const struct mmcsd_cmdinfo_s g_cmd58 = {CMD58, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R3, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd28 = {0x5c, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1B}; static const struct mmcsd_cmdinfo_s g_acmd23 = {ACMD23, MMCSD_CMDARG_NSECT, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd29 = {0x5d, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1B}; static const struct mmcsd_cmdinfo_s g_acmd41 = {ACMD41, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1, 0xff};
static const struct mmcsd_cmdinfo_s g_cmd30 = {0x5e, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1};
static const struct mmcsd_cmdinfo_s g_cmd32 = {0x60, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1};
static const struct mmcsd_cmdinfo_s g_cmd33 = {0x61, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1};
static const struct mmcsd_cmdinfo_s g_cmd34 = {0x62, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1};
static const struct mmcsd_cmdinfo_s g_cmd35 = {0x63, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1};
static const struct mmcsd_cmdinfo_s g_cmd36 = {0x64, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1};
static const struct mmcsd_cmdinfo_s g_cmd37 = {0x65, MMCSD_CMDARG_ADDRESS, MMCSD_CMDRESP_R1};
static const struct mmcsd_cmdinfo_s g_cmd38 = {0x66, MMCSD_CMDARG_DUMMY, MMCSD_CMDRESP_R1B};
static const struct mmcsd_cmdinfo_s g_cmd42 = {0x6a, MMCSD_CMDARG_DUMMY, MMCSD_CMDRESP_R1B};
static const struct mmcsd_cmdinfo_s g_cmd55 = {0x77, MMCSD_CMDARG_NONE, MMCSD_CMDRESP_R1};
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};
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
@@ -361,6 +346,9 @@ static void mmcsd_semtake(sem_t *sem)
* Description: * Description:
* Wait until the the card is no longer busy * Wait until the the card is no longer busy
* *
* Assumptions:
* MMC/SD card already selected
*
****************************************************************************/ ****************************************************************************/
static int mmcsd_waitready(FAR struct mmcsd_slot_s *slot) static int mmcsd_waitready(FAR struct mmcsd_slot_s *slot)
@@ -394,6 +382,9 @@ static int mmcsd_waitready(FAR struct mmcsd_slot_s *slot)
* Description: * Description:
* Send a command to MMC * Send a command to MMC
* *
* Assumptions:
* MMC/SD card already selected
*
****************************************************************************/ ****************************************************************************/
static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot, static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
@@ -404,10 +395,6 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
ubyte response = 0xff; ubyte response = 0xff;
int i; int i;
/* Select SPI */
SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
/* Send command code */ /* Send command code */
SPI_SEND(spi, cmd->cmd); SPI_SEND(spi, cmd->cmd);
@@ -430,19 +417,16 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
} }
/* Send CRC if needed. The SPI interface is initialized in non-protected /* Send CRC if needed. The SPI interface is initialized in non-protected
* mode. However, the reset command (CMD0) is received by the card while it * mode. However, the reset command (CMD0) and CMD8 are received by the
* is still in SD mode and, therefore, must have a valid CRC field. * card while it is still in SD mode and, therefore, must have a valid
* CRC field.
*/ */
if (cmd->cmd == 0x40) SPI_SEND(spi, cmd->chksum);
{
SPI_SEND(spi, 0x95); /* CRC for CMD0 */ /* Skip stuff byte on CMD12 */
}
else if (cmd->cmd == 0x58) if (cmd->cmd == CMD12)
{
SPI_SEND(spi, 0x87); /* CRC for CMD8 */
}
else
{ {
SPI_SEND(spi, 0xff); SPI_SEND(spi, 0xff);
} }
@@ -459,7 +443,6 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
if ((response & 0x80) != 0) if ((response & 0x80) != 0)
{ {
fdbg("Failed: i=%d response=%02x\n", i, response); fdbg("Failed: i=%d response=%02x\n", i, response);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
return (uint32)-1; return (uint32)-1;
} }
@@ -487,7 +470,6 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
if (busy != 0xff) if (busy != 0xff)
{ {
fdbg("Failed: card still busy (%02x)\n", busy); fdbg("Failed: card still busy (%02x)\n", busy);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
return (uint32)-1; return (uint32)-1;
} }
@@ -532,12 +514,11 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
slot->r7 |= ((uint32)(SPI_SEND(spi, 0xff) & 0xff) << 16); slot->r7 |= ((uint32)(SPI_SEND(spi, 0xff) & 0xff) << 16);
slot->r7 |= ((uint32)(SPI_SEND(spi, 0xff) & 0xff) << 8); slot->r7 |= ((uint32)(SPI_SEND(spi, 0xff) & 0xff) << 8);
slot->r7 |= SPI_SEND(spi, 0xff) & 0xff; slot->r7 |= SPI_SEND(spi, 0xff) & 0xff;
fvdbg("R1=%08x R7=%08x\n", response, slot->r7); fvdbg("R1=%02x R7=%08x\n", response, slot->r7);
} }
break; break;
} }
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
return result; return result;
} }
@@ -547,22 +528,27 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
* Description: * Description:
* Set block length * Set block length
* *
* Assumptions:
* MMC/SD card already selected
*
****************************************************************************/ ****************************************************************************/
static void mmcsd_setblklen(FAR struct mmcsd_slot_s *slot, uint32 length) static void mmcsd_setblklen(FAR struct mmcsd_slot_s *slot, uint32 length)
{ {
FAR struct spi_dev_s *spi = slot->spi; uint32 response;
uint32 result;
SPI_SELECT(spi, SPIDEV_MMCSD, TRUE); fvdbg("Set block length to %d\n", length);
result = mmcsd_sendcmd(slot, &g_cmd16, length); response = mmcsd_sendcmd(slot, &g_cmd16, length);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE); if (response != MMCSD_SPIR1_OK)
{
fdbg("Failed to set block length: %02x\n", response);
}
} }
/**************************************************************************** /****************************************************************************
* Name: mmcsd_nsac * Name: mmcsd_nsac
* *
* Description: Convert the value of the NSAC to millisconds * Description: Convert the value of the NSAC to microseconds
* *
****************************************************************************/ ****************************************************************************/
@@ -572,14 +558,15 @@ static uint32 mmcsd_nsac(FAR struct mmcsd_slot_s *slot, ubyte *csd, uint32 frequ
* maximum value is 25.5K clock cycles. * maximum value is 25.5K clock cycles.
*/ */
uint32 nsac = MMCSD_CSD_NSAC(csd) * 100000; uint32 nsac = MMCSD_CSD_NSAC(csd) * (100*1000); /* 1,000 * NSAC */
return (nsac + (frequency >> 1)) / frequency; uint32 fhkz = (frequency + 500) / 1000; /* frequency / 1,000 */
return (nsac + (fhkz >> 1)) / fhkz; /* 1,000,000 * NSAC / frequency */
} }
/**************************************************************************** /****************************************************************************
* Name: mmcsd_taac * Name: mmcsd_taac
* *
* Description: Convert the value of the TAAC to millisconds * Description: Convert the value of the TAAC to microseconds
* *
****************************************************************************/ ****************************************************************************/
@@ -601,17 +588,16 @@ static uint32 mmcsd_taac(FAR struct mmcsd_slot_s *slot, ubyte *csd)
if (tundx <= MAX_USTUNDX) if (tundx <= MAX_USTUNDX)
{ {
/* The maximum value of the nanosecond TAAC is 800 ns. The rounded /* The maximum value of the nanosecond TAAC is 800 ns. The rounded
* answer in milliseconds will always be zero. * answer in microseconds will be at most 1.
*/ */
return 0; return 1;
} }
else else
{ {
/* Return the answer in milliseconds */ /* Return the answer in microseconds */
uint32 taacus = (g_taactu[tundx]*g_taactv[MMCSD_CSD_TAAC_TIMEVALUE(csd)] + 0x80) >> 8; return (g_taactu[tundx]*g_taactv[MMCSD_CSD_TAAC_TIMEVALUE(csd)] + 0x80) >> 8;
return (taacus + 500) / 1000;
} }
} }
@@ -625,6 +611,7 @@ 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_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd)
{ {
FAR struct spi_dev_s *spi = slot->spi; FAR struct spi_dev_s *spi = slot->spi;
uint32 maxfrequency;
uint32 frequency; uint32 frequency;
uint32 readbllen; uint32 readbllen;
uint32 csizemult; uint32 csizemult;
@@ -632,16 +619,19 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd)
/* Calculate SPI max clock */ /* Calculate SPI max clock */
frequency = maxfrequency =
g_transpeedtu[MMCSD_CSD_TRANSPEED_TIMEVALUE(csd)] * g_transpeedtu[MMCSD_CSD_TRANSPEED_TIMEVALUE(csd)] *
g_transpeedru[MMCSD_CSD_TRANSPEED_TRANSFERRATEUNIT(csd)]; g_transpeedru[MMCSD_CSD_TRANSPEED_TRANSFERRATEUNIT(csd)];
/* Clip the max frequency to account for board limitations */
frequency = maxfrequency;
if (frequency > CONFIG_MMCSD_SPICLOCK) if (frequency > CONFIG_MMCSD_SPICLOCK)
{ {
frequency = CONFIG_MMCSD_SPICLOCK; frequency = CONFIG_MMCSD_SPICLOCK;
} }
/* Set the SPI frequency to that value */ /* Set the actual SPI frequency as close as possible to that value */
frequency = SPI_SETFREQUENCY(spi, frequency); frequency = SPI_SETFREQUENCY(spi, frequency);
@@ -655,20 +645,26 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd)
* *
* taccess = TU*TV + NSAC/spifrequency * taccess = TU*TV + NSAC/spifrequency
* *
* First get the access time in milliseconds. * Example: TAAC = 1.5 ms, NSAC = 0, r2wfactor = 4, CLK_TCK=100
* taccessus = 1,500uS
* taccess = (1,500 * 100) / 100,000) + 1 = 2 (ideal, 1.5)
* twrite = (1,500 * 4 * 100) / 100,000) + 1 = 7 (ideal 6.0)
*
* First get the access time in microseconds
*/ */
uint32 taccessms = mmcsd_taac(slot, csd) + mmcsd_nsac(slot, csd, frequency); uint32 taccessus = mmcsd_taac(slot, csd) + mmcsd_nsac(slot, csd, frequency);
/* Then convert to system clock ticks. The maximum read access is 10 * the /* Then convert to system clock ticks. The maximum read access is 10 times
* tacc value: taccess = 10 * taccessms / CLK_TCK / 1000, or * the tacc value: taccess = 10 * (taccessus / 1,000,000) * CLK_TCK, or
*/ */
slot->taccess = taccessms / CLK_TCK / 100 + 1; slot->taccess = (taccessus * CLK_TCK) / 100000 + 1;
/* The write access time is larger by the R2WFACTOR */ /* NOTE that we add one to taccess to assure that we wait at least this
* time. The write access time is larger by the R2WFACTOR: */
slot->twrite = taccessms * MMCSD_CSD_R2WFACTOR(csd) / CLK_TCK / 100 + 1; slot->taccess = (taccessus * MMCSD_CSD_R2WFACTOR(csd) * CLK_TCK) / 100000 + 1;
} }
else else
{ {
@@ -680,9 +676,11 @@ static void mmcsd_decodecsd(FAR struct mmcsd_slot_s *slot, ubyte *csd)
slot->twrite = SD_WRITEACCESS; slot->twrite = SD_WRITEACCESS;
} }
fvdbg("Frequency: %d\n", frequency); fvdbg("SPI Frequency\n");
fvdbg("Read access time: %d\n", slot->taccess); fvdbg(" Maximum: %d Hz\n", maxfrequency);
fvdbg("Write access time: %d\n", slot->twrite); fvdbg(" Actual: %d Hz\n", frequency);
fvdbg("Read access time: %d ticks\n", slot->taccess);
fvdbg("Write access time: %d ticks\n", slot->twrite);
/* Get the physical geometry of the card: sector size and number of /* Get the physical geometry of the card: sector size and number of
* sectors. The card's total capacity is computed from * sectors. The card's total capacity is computed from
@@ -772,6 +770,9 @@ static void mmcsd_checkwrprotect(FAR struct mmcsd_slot_s *slot, ubyte *csd)
* Description: * Description:
* Read CSD or CID registers * Read CSD or CID registers
* *
* Assumptions:
* MMC/SD card already selected
*
****************************************************************************/ ****************************************************************************/
static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer, static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
@@ -782,7 +783,6 @@ static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
ubyte response; ubyte response;
int i; int i;
SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
SPI_SEND(spi, 0xff); SPI_SEND(spi, 0xff);
/* Send the CMD9 or CMD10 */ /* Send the CMD9 or CMD10 */
@@ -791,7 +791,7 @@ static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
if (result != MMCSD_SPIR1_OK) if (result != MMCSD_SPIR1_OK)
{ {
fdbg("CMD9/10 failed: R1=%02x\n", result); fdbg("CMD9/10 failed: R1=%02x\n", result);
goto errout_with_eio; return -EIO;
} }
/* Try up to 8 times to find the start of block (or until an error occurs) */ /* Try up to 8 times to find the start of block (or until an error occurs) */
@@ -809,7 +809,7 @@ static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
if (response != 0 && (response & MMCSD_SPIDET_UPPER) == 0) if (response != 0 && (response & MMCSD_SPIDET_UPPER) == 0)
{ {
fdbg("%d. Data transfer error: %02x\n", i, response); fdbg("%d. Data transfer error: %02x\n", i, response);
goto errout_with_eio; return -EIO;
} }
else if (response == MMCSD_SPIDT_STARTBLKSNGL) else if (response == MMCSD_SPIDT_STARTBLKSNGL)
{ {
@@ -822,13 +822,11 @@ static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
SPI_SEND(spi, 0xff); SPI_SEND(spi, 0xff);
SPI_SEND(spi, 0xff); SPI_SEND(spi, 0xff);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
return OK; return OK;
} }
} }
errout_with_eio: fdbg("%d. Did not find start of block\n");
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
return -EIO; return -EIO;
} }
@@ -1127,7 +1125,7 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
SPI_SEND(spi, 0xff); SPI_SEND(spi, 0xff);
mmcsd_semgive(&slot->sem); mmcsd_semgive(&slot->sem);
fvdbg("(%d) Read %d bytes:\n", elapsed, nbytes); fvdbg("Read %d bytes:\n", nbytes);
mmcsd_dumpbuffer(buffer, nbytes); mmcsd_dumpbuffer(buffer, nbytes);
return nsectors; return nsectors;
@@ -1356,7 +1354,10 @@ static int mmcsd_geometry(FAR struct inode *inode, struct geometry *geometry)
/* Re-sample the CSD */ /* Re-sample the CSD */
mmcsd_semtake(&slot->sem); mmcsd_semtake(&slot->sem);
SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
ret = mmcsd_getcsd(slot, csd); ret = mmcsd_getcsd(slot, csd);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
if (ret < 0) if (ret < 0)
{ {
mmcsd_semgive(&slot->sem); mmcsd_semgive(&slot->sem);
@@ -1420,7 +1421,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
uint32 elapsed; uint32 elapsed;
int i, j; int i, j;
/* Assume that the card is not ready (we'll clear this on successful car /* Assume that the card is not ready (we'll clear this on successful card
* initialization. * initialization.
*/ */
@@ -1458,19 +1459,18 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
SPI_SELECT(spi, SPIDEV_MMCSD, TRUE); SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
SPI_SEND(spi, 0xff);
for (j = 10; j; j--) for (j = 10; j; j--)
{ {
SPI_SEND(spi, 0xff); SPI_SEND(spi, 0xff);
} }
/* Send CMD0 (GO_TO_IDLE) to put MMC/SD in IDLE/SPI mode */ /* Send CMD0 (GO_TO_IDLE) to put MMC/SD in IDLE/SPI mode.
* Return from CMD0 is R1 which should now show IDLE STATE
*/
result = mmcsd_sendcmd(slot, &g_cmd0, 0); result = mmcsd_sendcmd(slot, &g_cmd0, 0);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
/* Return from CMD0 is R1 which should now show IDLE STATE */
if (result == MMCSD_SPIR1_IDLESTATE) if (result == MMCSD_SPIR1_IDLESTATE)
{ {
fvdbg("Card is in IDLE state\n"); fvdbg("Card is in IDLE state\n");
@@ -1483,6 +1483,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
if (result != MMCSD_SPIR1_IDLESTATE) if (result != MMCSD_SPIR1_IDLESTATE)
{ {
fdbg("Send CMD0 failed: R1=%02x\n", result); fdbg("Send CMD0 failed: R1=%02x\n", result);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
return -EIO; return -EIO;
} }
@@ -1491,8 +1492,6 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
/* Check for SDHC Version 2.x. CMD 8 is reserved on SD version 1.0 and MMC. */ /* Check for SDHC Version 2.x. CMD 8 is reserved on SD version 1.0 and MMC. */
fvdbg("Send CMD8\n"); fvdbg("Send CMD8\n");
SPI_SELECT(spi, SPIDEV_MMCSD, TRUE);
SPI_SEND(spi, 0xff);
result = mmcsd_sendcmd(slot, &g_cmd8, 0x1aa); result = mmcsd_sendcmd(slot, &g_cmd8, 0x1aa);
if (result == MMCSD_SPIR1_IDLESTATE) if (result == MMCSD_SPIR1_IDLESTATE)
@@ -1641,7 +1640,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
mmcsd_decodecsd(slot, csd); mmcsd_decodecsd(slot, csd);
mmcsd_checkwrprotect(slot, csd); mmcsd_checkwrprotect(slot, csd);
/* SD Version block length is always 512 */ /* SD Version 2.xx block length is always 512 */
if (!IS_SDV2(slot->type)) if (!IS_SDV2(slot->type))
{ {
+42 -1
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* drivers/mmcsd/mmcsd_spi.h * drivers/mmcsd/mmcsd_spi.h
* *
* Copyright (C) 2008 Gregory Nutt. All rights reserved. * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,47 @@
****************************************************************************/ ****************************************************************************/
/* SPI *******************************************************************/ /* SPI *******************************************************************/
/* SPI Command Set */
#define CMD0 0x40 /* GO_IDLE_STATE: Resets all cards to idle state */
#define CMD1 0x41 /* SEND_OP_COND: Sends capacity support information */
#define CMD6 0x46 /* SWITCH_FUNC: Checks switchable function */
#define CMD8 0x48 /* SEND_IF_COND: Sends SD Memory Card interface condition */
#define CMD9 0x49 /* SEND_CSD: Asks card to send its card specific data (CSD) */
#define CMD10 0x4a /* SEND_CID: Asks card to send its card identification (CID) */
#define CMD12 0x4c /* STOP_TRANSMISSION: Forces the card to stop transmission */
#define CMD13 0x4d /* SEND_STATUS: Asks card to send its status register */
#define CMD16 0x50 /* SET_BLOCKLEN: Sets a block length (in bytes) */
#define CMD17 0x51 /* READ_SINGLE_BLOCK: Reads a block of the selected size */
#define CMD18 0x52 /* READ_MULTIPLE_BLOCK: Continuously transfers blocks from card to host */
#define CMD20 0x54 /* CMD_WRITEBLOCK: Write block to memory (MMC) */
#define CMD24 0x58 /* WRITE_BLOCK: Writes a block of the selected size */
#define CMD25 0x59 /* WRITE_MULTIPLE_BLOCK: Continuously writes blocks of data */
#define CMD27 0x5b /* PROGRAM_CSD: Set programmable bits of the CSD */
#define CMD28 0x5c /* SET_WRITE_PROT: Sets the write protection bit of group */
#define CMD29 0x5d /* CLR_WRITE_PROT: Clears the write protection bit of group */
#define CMD30 0x5e /* SEND_WRITE_PROT: Asks card to send state of write protection bits */
#define CMD32 0x60 /* ERASE_WR_BLK_START_ADDR: Sets address of first block to erase */
#define CMD33 0x61 /* ERASE_WR_BLK_END_ADDR: Sets address of last block to erase */
#define CMD34 0x62 /* UNTAG_SECTOR: (MMC) */
#define CMD35 0x63 /* TAG_ERASE_GROUP_START: (MMC) */
#define CMD36 0x64 /* TAG_ERASE_GOUPR_END: (MMC) */
#define CMD37 0x65 /* UNTAG_ERASE_GROUP: (MMC) */
#define CMD38 0x66 /* ERASE: Erases all previously selected write blocks */
#define CMD40 0x68 /* CRC_ON_OFF: (MMC) */
#define CMD42 0x6a /* LOCK_UNLOCK: Used to Set/Reset the Password or lock/unlock card */
#define CMD55 0x77 /* APP_CMD: Tells card that the next command is an application specific command */
#define CMD56 0x78 /* GEN_CMD: Used transfer a block to or get block from card */
#define CMD58 0x7a /* READ_OCR :Reads the OCR register of a card */
#define CMD59 0x7b /* CRC_ON_OFF: Turns the CRC option on or off */
#define ACMD13 0x4d /* SD_STATUS: Send the SD Status */
#define ACMD22 0x56 /* SEND_NUM_WR_BLOCKS: Send number of the errorfree blocks */
#define ACMD23 0x57 /* SET_WR_BLK_ERASE_COUNT: Set number blocks to erase before writing */
#define ACMD41 0x69 /* SD_SEND_OP_COND: Sends host capacity support information */
#define ACMD42 0x6a /* SET_CLR_CARD_DETECT: Connect/disconnect pull-up resistor on CS */
#define ACMD51 0x73 /* SEND_SCR: Reads the SD Configuration Register (SCR) */
/* SPI 8-bit R1 response */ /* SPI 8-bit R1 response */
#define MMCSD_SPIR1_OK 0x00 /* No error bits set */ #define MMCSD_SPIR1_OK 0x00 /* No error bits set */