Add SD card initialization logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2258 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
95908c8777
commit
529bbb7a2a
@ -123,6 +123,7 @@ static inline void stm32_dmaenable(void);
|
||||
|
||||
/* Data Transfer Helpers ****************************************************/
|
||||
|
||||
static ubyte stm32_log2(uint16 value);
|
||||
static void stm32_dataconfig(uint32 timeout, uint32 dlen, uint32 dctrl);
|
||||
static void stm32_datadisable(void);
|
||||
|
||||
@ -135,13 +136,12 @@ static ubyte stm32_status(FAR struct sdio_dev_s *dev);
|
||||
static void stm32_widebus(FAR struct sdio_dev_s *dev, boolean enable);
|
||||
static void stm32_clock(FAR struct sdio_dev_s *dev,
|
||||
enum sdio_clock_e rate);
|
||||
static int stm32_setblocklen(FAR struct sdio_dev_s *dev, int blocklen,
|
||||
int nblocks);
|
||||
static int stm32_attach(FAR struct sdio_dev_s *dev);
|
||||
|
||||
/* Command/Status/Data Transfer */
|
||||
|
||||
static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 arg);
|
||||
static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 arg);
|
||||
static int stm32_sendsetup(FAR struct sdio_dev_s *dev, uint32 nbytes);
|
||||
static int stm32_senddata(FAR struct sdio_dev_s *dev,
|
||||
FAR const ubyte *buffer);
|
||||
|
||||
@ -150,11 +150,12 @@ static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *
|
||||
static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 rlong[4]);
|
||||
static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *rshort);
|
||||
static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *rnotimpl);
|
||||
static int stm32_recvsetup(FAR struct sdio_dev_s *dev, uint32 nbytes);
|
||||
static int stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer);
|
||||
|
||||
/* EVENT handler */
|
||||
|
||||
static void stm32_eventenable(FAR struct sdio_dev_s *dev, ubyte eventset,
|
||||
static void stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset,
|
||||
boolean enable);
|
||||
static ubyte stm32_eventwait(FAR struct sdio_dev_s *dev, uint32 timeout);
|
||||
static ubyte stm32_events(FAR struct sdio_dev_s *dev);
|
||||
@ -194,9 +195,9 @@ struct stm32_dev_s g_mmcsd =
|
||||
.status = stm32_status,
|
||||
.widebus = stm32_widebus,
|
||||
.clock = stm32_clock,
|
||||
.setblocklen = stm32_setblocklen,
|
||||
.attach = stm32_attach,
|
||||
.sendcmd = stm32_sendcmd,
|
||||
.sendcmd = stm32_sendcmd,
|
||||
.sendsetup = stm32_sendsetup,
|
||||
.senddata = stm32_senddata,
|
||||
.waitresponse = stm32_waitresponse,
|
||||
.recvR1 = stm32_recvshortcrc,
|
||||
@ -205,7 +206,8 @@ struct stm32_dev_s g_mmcsd =
|
||||
.recvR4 = stm32_recvnotimpl,
|
||||
.recvR5 = stm32_recvnotimpl,
|
||||
.recvR6 = stm32_recvshortcrc,
|
||||
.recvR7 = stm32_recvshort,
|
||||
.recvR7 = stm32_recvshort,
|
||||
.recvsetup = stm32_recvsetup,
|
||||
.recvdata = stm32_recvdata,
|
||||
.eventenable = stm32_eventenable,
|
||||
.eventwait = stm32_eventwait,
|
||||
@ -378,6 +380,37 @@ static inline void stm32_dmaenable(void)
|
||||
/****************************************************************************
|
||||
* Data Transfer Helpers
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_log2
|
||||
*
|
||||
* Description:
|
||||
* Take (approximate) log base 2 of the provided number (Only works if the
|
||||
* provided number is a power of 2).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ubyte stm32_log2(uint16 value)
|
||||
{
|
||||
ubyte log2 = 0;
|
||||
|
||||
/* 0000 0000 0000 0001 -> return 0,
|
||||
* 0000 0000 0000 001x -> return 1,
|
||||
* 0000 0000 0000 01xx -> return 2,
|
||||
* 0000 0000 0000 1xxx -> return 3,
|
||||
* ...
|
||||
* 1xxx xxxx xxxx xxxx -> return 15,
|
||||
*/
|
||||
|
||||
DEBUGASSERT(value > 0);
|
||||
while (value != 1)
|
||||
{
|
||||
value >>= 1;
|
||||
log2++;
|
||||
}
|
||||
return log2;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_dataconfig
|
||||
*
|
||||
@ -490,7 +523,11 @@ static ubyte stm32_status(FAR struct sdio_dev_s *dev)
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_widebus(FAR struct sdio_dev_s *dev, boolean wide)
|
||||
{
|
||||
{
|
||||
if (wide)
|
||||
{
|
||||
priv->mode = MMCSDMODE_DMA;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -512,27 +549,6 @@ static void stm32_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_setblocklen
|
||||
*
|
||||
* Description:
|
||||
* Set the MMC/SD block length and block count
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* blocklen - The block length
|
||||
* nblocks - The block count
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_setblocklen(FAR struct sdio_dev_s *dev, int blocklen, int nblocks)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_attach
|
||||
*
|
||||
@ -616,6 +632,31 @@ static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 arg)
|
||||
putreg32(regval, STM32_SDIO_CMD);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_sendsetup
|
||||
*
|
||||
* Description:
|
||||
* Setup hardware in preparation for data trasfer from the card. This method
|
||||
* will do whatever controller setup is necessary. This would be called
|
||||
* for SD memory just AFTER sending CMD24 (WRITE_BLOCK), CMD25
|
||||
* (WRITE_MULTIPLE_BLOCK), ... and before SDIO_SENDDATA is called.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* nbytes - The number of bytes in the transfer
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes sent on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_sendsetup(FAR struct sdio_dev_s *dev, uint32 nbytes)
|
||||
{
|
||||
uint32 dctrl = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT);
|
||||
stm32_dataconfig(SD_DATATIMEOUT, nbytes, dctrl);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_senddata
|
||||
*
|
||||
@ -627,7 +668,7 @@ static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 arg)
|
||||
* data - Data to be sent
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes sent on succes; a negated errno on failure
|
||||
* Number of bytes sent on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -918,6 +959,32 @@ static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *rno
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_recvsetup
|
||||
*
|
||||
* Description:
|
||||
* Setup hardware in preparation for data trasfer from the card. This method
|
||||
* will do whatever controller setup is necessary. This would be called
|
||||
* for SD memory just BEFORE sending CMD13 (SEND_STATUS), CMD17
|
||||
* (READ_SINGLE_BLOCK), CMD18 (READ_MULTIPLE_BLOCKS), ACMD51 (SEND_SCR), ...
|
||||
* and before SDIO_RECVDATA is called.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* nbytes - The number of bytes in the transfer
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes sent on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_recvsetup(FAR struct sdio_dev_s *dev, uint32 nbytes)
|
||||
{
|
||||
uint32 dctrl = (stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT)) | SDIO_DCTRL_DTDIR;
|
||||
stm32_dataconfig(SD_DATATIMEOUT, nbytes, dctrl);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_recvdata
|
||||
*
|
||||
@ -929,7 +996,7 @@ static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *rno
|
||||
* buffer - Buffer in which to receive the data
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes sent on succes; a negated errno on failure
|
||||
* Number of bytes sent on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -947,16 +1014,14 @@ static int stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* eventset - A bitset of events to enable or disable (see MMCSDEVENT_*
|
||||
* definitions
|
||||
* enable - TRUE: enable event; FALSE: disable events
|
||||
* definitions). 0=disable; 1=enable.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_eventenable(FAR struct sdio_dev_s *dev, ubyte eventset,
|
||||
boolean enable)
|
||||
static void stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
|
||||
{
|
||||
}
|
||||
|
||||
@ -972,7 +1037,8 @@ static void stm32_eventenable(FAR struct sdio_dev_s *dev, ubyte eventset,
|
||||
*
|
||||
* Returned Value:
|
||||
* Event set containing the event(s) that ended the wait. If no events the
|
||||
* returned event set is zero, then the wait was terminated by the timeout.
|
||||
* returned event set is zero, then the wait was terminated by the timeout.
|
||||
* All events are cleared disabled after the wait concludes.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -986,13 +1052,14 @@ static ubyte stm32_eventwait(FAR struct sdio_dev_s *dev, uint32 timeout)
|
||||
*
|
||||
* Description:
|
||||
* Return the current event set. This supports polling for MMC/SD (vs.
|
||||
* waiting).
|
||||
* waiting). Only enabled events need be reported.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
*
|
||||
* Returned Value:
|
||||
* Event set containing the current events (cleared after reading).
|
||||
* Event set containing the current events (All pending events are cleared
|
||||
* after reading).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1062,7 +1129,7 @@ static void stm32_coherent(FAR struct sdio_dev_s *dev, FAR void *addr,
|
||||
* buffer - The memory to DMA from
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1084,7 +1151,7 @@ static int tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
|
||||
* buffer - The memory to DMA into
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1106,7 +1173,7 @@ static int stm32_dmawritesetup(FAR struct sdio_dev_s *dev,
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1127,7 +1194,7 @@ static int stm32_dmastart(FAR struct sdio_dev_s *dev)
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1150,7 +1217,7 @@ static int stm32_dmastop(FAR struct sdio_dev_s *dev)
|
||||
* remaining in the transfer.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -76,6 +76,10 @@
|
||||
#define MMCSD_DSR_DELAY (100*1000) /* Time to wait after setting DSR */
|
||||
#define MMCSD_CLK_DELAY (500*1000) /* Delay after changing clock speeds */
|
||||
|
||||
/* Event delays (all in units of milliseconds) */
|
||||
|
||||
#define MMCSD_SCR_DATADELAY (100) /* Wait up to 100MS to get SCR */
|
||||
|
||||
#define IS_EMPTY(priv) (priv->type == MMCSD_CARDTYPE_UNKNOWN)
|
||||
|
||||
/* Transfer mode */
|
||||
@ -109,6 +113,7 @@ struct mmcsd_state_s
|
||||
|
||||
ubyte mode:2; /* (See MMCSDMODE_* definitions) */
|
||||
ubyte type:4; /* Card type (See MMCSD_CARDTYPE_* definitions) */
|
||||
ubyte buswidth:4; /* Bus widthes supported (SD only) */
|
||||
uint16 selblocklen; /* The currently selected block length */
|
||||
uint16 rca; /* Relative Card Address (RCS) register */
|
||||
|
||||
@ -131,17 +136,21 @@ struct mmcsd_state_s
|
||||
|
||||
/* Command/response helpers *************************************************/
|
||||
|
||||
static int mmcsd_sendcmdpoll(struct mmcsd_state_s *priv, uint32 cmd, uint32 arg);
|
||||
|
||||
static int mmcsd_sendcmdpoll(struct mmcsd_state_s *priv, uint32 cmd,
|
||||
uint32 arg);
|
||||
static int mmcsd_recvR1(struct mmcsd_state_s *priv, uint32 cmd);
|
||||
static void mmcsd_decodecsd(struct mmcsd_state_s *priv, uint32 csd[4]);
|
||||
static int mmcsd_getSCR(struct mmcsd_state_s *priv, uint32 scr[2]);
|
||||
|
||||
static void mmcsd_decodeCSD(struct mmcsd_state_s *priv, uint32 csd[4]);
|
||||
#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
static void mmcsd_decodecid(struct mmcsd_state_s *priv, uint32 cid[4]);
|
||||
static void mmcsd_decodeCID(struct mmcsd_state_s *priv, uint32 cid[4]);
|
||||
#else
|
||||
# define mmcsd_decodecid(priv,cid)
|
||||
# define mmcsd_decodeCID(priv,cid)
|
||||
#endif
|
||||
static void mmcsd_decodeSCR(struct mmcsd_state_s *priv, uint32 scr[2]);
|
||||
|
||||
static int mmcsd_verifystandby(struct mmcsd_state_s *priv);
|
||||
static int mmcsd_verifyidle(struct mmcsd_state_s *priv);
|
||||
|
||||
/* Transfer helpers *********************************************************/
|
||||
|
||||
@ -167,17 +176,14 @@ static int mmcsd_ioctl(FAR struct inode *inode, int cmd,
|
||||
|
||||
/* Initialization/uninitialization/reset ************************************/
|
||||
|
||||
static inline int
|
||||
mmcsd_mmcinitialize(struct mmcsd_state_s *priv);
|
||||
static inline int
|
||||
mmcsd_sdinitialize(struct mmcsd_state_s *priv);
|
||||
static inline int
|
||||
mmcsd_cardidentify(struct mmcsd_state_s *priv);
|
||||
static int mmcsd_widebus(struct mmcsd_state_s *priv);
|
||||
static int mmcsd_mmcinitialize(struct mmcsd_state_s *priv);
|
||||
static int mmcsd_sdinitialize(struct mmcsd_state_s *priv);
|
||||
static int mmcsd_cardidentify(struct mmcsd_state_s *priv);
|
||||
static int mmcsd_probe(struct mmcsd_state_s *priv);
|
||||
static int mmcsd_removed(struct mmcsd_state_s *priv);
|
||||
static int mmcsd_hwinitialize(struct mmcsd_state_s *priv);
|
||||
static inline void
|
||||
mmcsd_hwuninitialize(struct mmcsd_state_s *priv);
|
||||
static void mmcsd_hwuninitialize(struct mmcsd_state_s *priv);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@ -299,7 +305,75 @@ static int mmcsd_recvR1(struct mmcsd_state_s *priv, uint32 cmd)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mmcsd_decodecsd
|
||||
* Name: mmcsd_getSCR
|
||||
*
|
||||
* Description:
|
||||
* Obtain the SD card's Configuration Register (SCR)
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; a negated ernno on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int mmcsd_getSCR(struct mmcsd_state_s *priv, uint32 scr[2])
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Set Block Size To 8 Bytes */
|
||||
/* Send CMD55 APP_CMD with argument as card's RCA */
|
||||
|
||||
mmcsd_sendcmdpoll(priv, MMCSD_CMD16, 8);
|
||||
ret = mmcsd_recvR1(priv, MMCSD_CMD16);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: RECVR1 for CMD16 failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Send CMD55 APP_CMD with argument as card's RCA */
|
||||
|
||||
mmcsd_sendcmdpoll(priv, SD_CMD55, (uint32)priv->rca << 16);
|
||||
ret = mmcsd_recvR1(priv, SD_CMD55);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: RECVR1 for CMD55 failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Setup up to receive data */
|
||||
|
||||
SDIO_RECVSETUP(priv->dev, 8);
|
||||
|
||||
/* Send ACMD51 SD_APP_SEND_SCR with argument as 0 to start data receipt */
|
||||
|
||||
(void)SDIO_EVENTENABLE(priv->dev, SDIOEVENT_READDATADONE);
|
||||
mmcsd_sendcmdpoll(priv, SD_ACMD51, 0);
|
||||
ret = mmcsd_recvR1(priv, SD_ACMD51);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: RECVR1 for ACMD51 failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Wait for data available */
|
||||
|
||||
ret = SDIO_EVENTWAIT(priv->dev, MMCSD_SCR_DATADELAY);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: WAITEVENT for READ DATA failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Receive the SCR data from the SD card. Card data is sent big-endian;
|
||||
* if we are running on a little-endian machine, then we need to swap
|
||||
* some bytes (should this be a configuration option?)
|
||||
*/
|
||||
|
||||
return SDIO_RECVDATA(priv->dev, (FAR ubyte *)scr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mmcsd_decodeCSD
|
||||
*
|
||||
* Description:
|
||||
* Decode and extract necessary information from the CSD. If debug is
|
||||
@ -316,7 +390,7 @@ static int mmcsd_recvR1(struct mmcsd_state_s *priv, uint32 cmd)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void mmcsd_decodecsd(struct mmcsd_state_s *priv, uint32 csd[4])
|
||||
static void mmcsd_decodeCSD(struct mmcsd_state_s *priv, uint32 csd[4])
|
||||
{
|
||||
#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
struct mmcsd_csd_s decoded;
|
||||
@ -563,15 +637,16 @@ static void mmcsd_decodecsd(struct mmcsd_state_s *priv, uint32 csd[4])
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mmcsd_decodecid
|
||||
* Name: mmcsd_decodeCID
|
||||
*
|
||||
* Description:
|
||||
* Show the contents of the CID (for debug purposes only)
|
||||
* Show the contents of the Card Indentification Data (CID) (for debug
|
||||
* purposes only)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
static void mmcsd_decodecid(struct mmcsd_state_s *priv, uint32 cid[4])
|
||||
static void mmcsd_decodeCID(struct mmcsd_state_s *priv, uint32 cid[4])
|
||||
{
|
||||
struct mmcsd_cid_s decoded;
|
||||
|
||||
@ -625,11 +700,66 @@ static void mmcsd_decodecid(struct mmcsd_state_s *priv, uint32 cid[4])
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mmcsd_decodeSCR
|
||||
*
|
||||
* Description:
|
||||
* Show the contents of the SD Configuration Register (SCR). The only
|
||||
* value retained is: priv->buswidth;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void mmcsd_decodeSCR(struct mmcsd_state_s *priv, uint32 scr[2])
|
||||
{
|
||||
#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
struct mmcsd_scr_s decoded;
|
||||
#endif
|
||||
|
||||
/* Word 1, bits 63:32
|
||||
* SCR_STRUCTURE 63:60 4-bit SCR structure version
|
||||
* SD_VERSION 59:56 4-bit SD memory spec. version
|
||||
* DATA_STATE_AFTER_ERASE 55:55 1-bit erase status
|
||||
* SD_SECURITY 54:52 3-bit SD security support level
|
||||
* SD_BUS_WIDTHS 51:48 4-bit bus width indicator
|
||||
* Reserved 47:32 16-bit SD reserved space
|
||||
* usage.
|
||||
*
|
||||
*/
|
||||
|
||||
priv->buswidth = (scr[0] >> 16) & 15;
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
decoded.scrversion = scr[0] >> 28;
|
||||
decoded.sdversion = (scr[0] >> 24) & 15;
|
||||
decoded.erasestate = (scr[0] >> 23) & 1;
|
||||
decoded.security = (scr[0] >> 20) & 7;
|
||||
decoded.buswidth = priv->buswidth;
|
||||
#endif
|
||||
|
||||
/* Word 1, bits 63:32
|
||||
* Reserved 31:0 32-bits reserved for manufacturing
|
||||
* usage.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS)
|
||||
decoded.mfgdata = scr[1];
|
||||
|
||||
fvdbg("SCR:\n");
|
||||
fvdbg(" SCR_STRUCTURE: %d SD_VERSION: %d\n",
|
||||
decoded.scrversion,decoded.sdversion);
|
||||
fvdbg(" DATA_STATE_AFTER_ERASE: %d SD_SECURITY: %d SD_BUS_WIDTHS: %x\n",
|
||||
decoded.erasestate, decoded.security, decoded.buswidth);
|
||||
fvdbg(" Manufacturing data: %08x\n",
|
||||
decoded.mfgdata);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mmcsd_verifystandby
|
||||
*
|
||||
* Description:
|
||||
* Verify that the card is in standby state
|
||||
* Verify that the card is in STANDBY state
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -639,6 +769,20 @@ static int mmcsd_verifystandby(struct mmcsd_state_s *priv)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mmcsd_verifystandby
|
||||
*
|
||||
* Description:
|
||||
* Verify that the card is in IDLE state
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int mmcsd_verifyidle(struct mmcsd_state_s *priv)
|
||||
{
|
||||
#warning "Not implemented"
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Transfer Helpers
|
||||
****************************************************************************/
|
||||
@ -891,6 +1035,93 @@ static int mmcsd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
|
||||
* Initialization/uninitialization/reset
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mmcsd_widebus
|
||||
*
|
||||
* Description:
|
||||
* An SD card has been inserted and its SCR has been obtained. Select wide
|
||||
* (4-bit) bus operation if the card supports it.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called only once per card insertion as part of the SD
|
||||
* card initialization sequence. It is not necessary to reselect the card
|
||||
* there is not need to check if wide bus operation has already been
|
||||
* selected.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int mmcsd_widebus(struct mmcsd_state_s *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Check if the SD card supports this feature (as reported in the SCR) */
|
||||
|
||||
if ((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0)
|
||||
{
|
||||
/* Disconnect any CD/DAT3 pull up using ACMD42. ACMD42 is optional and
|
||||
* need not be supported by all SD calls.
|
||||
*
|
||||
* First end CMD55 APP_CMD with argument as card's RCA.
|
||||
*/
|
||||
|
||||
mmcsd_sendcmdpoll(priv, SD_CMD55, (uint32)priv->rca << 16);
|
||||
ret = mmcsd_recvR1(priv, SD_CMD55);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: RECVR1 for CMD55 of ACMD42: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Then send ACMD42 with the argument to disconnect the CD/DAT3
|
||||
* pullup
|
||||
*/
|
||||
|
||||
mmcsd_sendcmdpoll(priv, SD_ACMD42, MMCSD_ACMD42_CD_DISCONNECT);
|
||||
ret = mmcsd_recvR1(priv, SD_ACMD42);
|
||||
if (ret != OK)
|
||||
{
|
||||
fvdbg("WARNING: SD card does not support ACMD42: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Now send ACMD6 to select wide, 4-bit bus operation, beginning
|
||||
* with CMD55, APP_CMD:
|
||||
*/
|
||||
|
||||
mmcsd_sendcmdpoll(priv, SD_CMD55, (uint32)priv->rca << 16);
|
||||
ret = mmcsd_recvR1(priv, SD_CMD55);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: RECVR1 for CMD55 of ACMD6: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Then send ACMD6 */
|
||||
|
||||
mmcsd_sendcmdpoll(priv, SD_ACMD6, MMCSD_ACMD6_BUSWIDTH_4);
|
||||
ret = mmcsd_recvR1(priv, SD_ACMD6);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure the SDIO peripheral */
|
||||
|
||||
fvdbg("Wide bus operation selected\n");
|
||||
SDIO_WIDEBUS(priv->dev, TRUE);
|
||||
priv->widebus = TRUE;
|
||||
|
||||
SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_4BIT);
|
||||
up_udelay(MMCSD_CLK_DELAY);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Wide bus operation not supported */
|
||||
|
||||
fdbg("WARNING: Card does not support wide-bus operation\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mmcsd_mmcinitialize
|
||||
*
|
||||
@ -900,7 +1131,7 @@ static int mmcsd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int mmcsd_mmcinitialize(struct mmcsd_state_s *priv)
|
||||
static int mmcsd_mmcinitialize(struct mmcsd_state_s *priv)
|
||||
{
|
||||
#ifdef CONFIG_MMCSD_MMCSUPPORT
|
||||
uint32 cid[4];
|
||||
@ -912,7 +1143,7 @@ static inline int mmcsd_mmcinitialize(struct mmcsd_state_s *priv)
|
||||
* so there is good evidence that we have an MMC card inserted into the
|
||||
* slot.
|
||||
*
|
||||
* Send CMD2 = ALL_SEND_CID. This implementation supports only one MMC slot.
|
||||
* Send CMD2, ALL_SEND_CID. This implementation supports only one MMC slot.
|
||||
* If mulitple cards were installed, each card would respond to CMD2 by
|
||||
* sending its CID (only one card completes the response at a time). The
|
||||
* driver should send CMD2 and assign an RCAs until no response to
|
||||
@ -926,9 +1157,9 @@ static inline int mmcsd_mmcinitialize(struct mmcsd_state_s *priv)
|
||||
fdbg("ERROR: SDIO_RECVR2 for MMC CID failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mmcsd_decodecid(priv, cid);
|
||||
mmcsd_decodeCID(priv, cid);
|
||||
|
||||
/* Send CMD3 = SET_RELATIVE_ADDR. This command is used to assign a logical
|
||||
/* Send CMD3, SET_RELATIVE_ADDR. This command is used to assign a logical
|
||||
* address to the card. For MMC, the host assigns the address. CMD3 causes
|
||||
* transition to standby state/data-transfer mode
|
||||
*/
|
||||
@ -936,7 +1167,7 @@ static inline int mmcsd_mmcinitialize(struct mmcsd_state_s *priv)
|
||||
priv->rca = 1; /* There is only one card */
|
||||
mmcsd_sendcmdpoll(priv, MMC_CMD3, priv->rca << 16);
|
||||
ret = mmcsd_recvR1(priv, MMC_CMD3);
|
||||
if (ret != 0)
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: mmcsd_recvR1(CMD3) failed: %d\n", ret);
|
||||
return ret;
|
||||
@ -950,25 +1181,25 @@ static inline int mmcsd_mmcinitialize(struct mmcsd_state_s *priv)
|
||||
*/
|
||||
|
||||
ret = mmcsd_verifystandby(priv);
|
||||
if (ret != 0)
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: Failed to enter standby state\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Send CMD9 = SEND_CSD in standby state/data-transfer mode to obtain the
|
||||
/* Send CMD9, SEND_CSD in standby state/data-transfer mode to obtain the
|
||||
* Card Specific Data (CSD) register, e.g., block length, card storage
|
||||
* capacity, etc. (Stays in standy state/data-transfer mode)
|
||||
*/
|
||||
|
||||
mmcsd_sendcmdpoll(priv, MMCSD_CMD9, priv->rca << 16);
|
||||
ret = SDIO_RECVR2(priv->dev, MMCSD_CMD9, csd);
|
||||
if (ret != 0)
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: Could not get SD CSD register: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mmcsd_decodecsd(priv, csd);
|
||||
mmcsd_decodeCSD(priv, csd);
|
||||
|
||||
/* Set the Driver Stage Register (DSR) if (1) a CONFIG_MMCSD_DSR has been
|
||||
* provided and (2) the card supports a DSR register. If no DSR value
|
||||
@ -994,9 +1225,120 @@ static inline int mmcsd_mmcinitialize(struct mmcsd_state_s *priv)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int mmcsd_sdinitialize(struct mmcsd_state_s *priv)
|
||||
static int mmcsd_sdinitialize(struct mmcsd_state_s *priv)
|
||||
{
|
||||
return -ENOSYS;
|
||||
uint32 cid[4];
|
||||
uint32 csd[4];
|
||||
uint32 scr[2];
|
||||
uint32 rca;
|
||||
int ret;
|
||||
|
||||
/* At this point, clocking has been supplied to the card, both CMD0 and
|
||||
* ACMD41 (with OCR=0) have been sent successfully, the card is no longer
|
||||
* busy and (presumably) in the IDLE state so there is good evidence
|
||||
* that we have an SD card inserted into the slot.
|
||||
*
|
||||
* Send CMD2, ALL_SEND_CID. The SD CMD2 is similar to the MMC CMD2 except
|
||||
* that the buffer type used to transmit to response of the card (SD Memory
|
||||
* Card: Push-Pull, MMC: Open-Drain). This implementation supports only a
|
||||
* single SD card. If multiple cards were installed in the slot, each card
|
||||
* would respond to CMD2 by sending its CID (only one card completes the
|
||||
* response at a time). The driver should send CMD2 and obtain RCAs until
|
||||
* no response to ALL_SEND_CID is received.
|
||||
*
|
||||
* When an SD card receives the CMD2 command it should transition to the
|
||||
* identification state/card-identification mode
|
||||
*/
|
||||
|
||||
mmcsd_sendcmdpoll(priv, MMCSD_CMD2, 0);
|
||||
ret = SDIO_RECVR2(priv->dev, MMCSD_CMD2, cid);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: SDIO_RECVR2 for SD CID failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mmcsd_decodeCID(priv, cid);
|
||||
|
||||
/* Send CMD3, SET_RELATIVE_ADDR. In both protocols, this command is used
|
||||
* to assign a logical address to the card. For MMC, the host assigns the
|
||||
* address; for SD, the memory card has this responsibility. CMD3 causes
|
||||
* transition to standby state/data-transfer mode
|
||||
*
|
||||
* Send CMD3 with argument 0, SD card publishes its RCA in the response.
|
||||
*/
|
||||
|
||||
mmcsd_sendcmdpoll(priv, SD_CMD3, 0);
|
||||
ret = SDIO_RECVR6(priv->dev, SD_CMD3, &rca);
|
||||
if (ret != OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->rca = (uint16)rca;
|
||||
fvdbg("RCA: %04x\n", priv->rca);
|
||||
|
||||
/* This should have caused a transition to standby state. However, this will
|
||||
* not be reflected in the present R1 status. R1/6 contains the state of
|
||||
* the card when the command was received, not when it completed execution.
|
||||
*
|
||||
* Verify that we are in standby state/data-transfer mode
|
||||
*/
|
||||
|
||||
ret = mmcsd_verifystandby(priv);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: Failed to enter standby state\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Send CMD9, SEND_CSD, in standby state/data-transfer mode to obtain the
|
||||
* Card Specific Data (CSD) register. The argument is the RCA that we
|
||||
* just obtained from CMD3. The card stays in standy state/data-transfer
|
||||
* mode.
|
||||
*/
|
||||
|
||||
mmcsd_sendcmdpoll(priv, MMCSD_CMD9, priv->rca << 16);
|
||||
ret = SDIO_RECVR2(priv->dev, MMCSD_CMD9, csd);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: Could not get SD CSD register(%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mmcsd_decodeCSD(priv, csd);
|
||||
|
||||
/* Set the Driver Stage Register (DSR) if (1) a CONFIG_MMCSD_DSR has been
|
||||
* provided and (2) the card supports a DSR register. If no DSR value
|
||||
* the card default value (0x0404) will be used.
|
||||
*/
|
||||
|
||||
(void)mmcsd_sendcmd4(priv);
|
||||
|
||||
/* Select high speed SD clocking (which may depend on the DSR setting) */
|
||||
|
||||
SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_1BIT);
|
||||
up_udelay(MMCSD_CLK_DELAY);
|
||||
|
||||
/* Get the SD card Configuration Register (SCR). We need this now because
|
||||
* that configuration register contains the indication whether or not
|
||||
* this card supports wide bus operation.\
|
||||
*/
|
||||
|
||||
ret = mmcsd_getSCR(priv, scr);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: Could not get SD SCR register(%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
mmcsd_decodeSCR(priv, scr);
|
||||
|
||||
/* Select width (4-bit) bus operation (if the card supports it) */
|
||||
|
||||
ret = mmcsd_widebus(priv);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("WARN: Failed to set wide bus operation: %d\n", ret);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -1008,12 +1350,12 @@ static inline int mmcsd_sdinitialize(struct mmcsd_state_s *priv)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int mmcsd_cardidentify(struct mmcsd_state_s *priv)
|
||||
static int mmcsd_cardidentify(struct mmcsd_state_s *priv)
|
||||
{
|
||||
uint32 response;
|
||||
uint32 start;
|
||||
uint32 elapsed;
|
||||
uint32 sdcapacity = MMCD_ACMD41_STDCAPACITY;
|
||||
uint32 sdcapacity = MMCSD_ACMD41_STDCAPACITY;
|
||||
int ret;
|
||||
|
||||
/* Assume failure to identify the card */
|
||||
@ -1074,7 +1416,7 @@ static inline int mmcsd_cardidentify(struct mmcsd_state_s *priv)
|
||||
{
|
||||
fvdbg("SD V2.x card\n");
|
||||
priv->type = MMCSD_CARDTYPE_SDV2;
|
||||
sdcapacity = MMCD_ACMD41_HIGHCAPACITY;
|
||||
sdcapacity = MMCSD_ACMD41_HIGHCAPACITY;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1119,7 +1461,7 @@ static inline int mmcsd_cardidentify(struct mmcsd_state_s *priv)
|
||||
{
|
||||
/* Send ACMD41 */
|
||||
|
||||
mmcsd_sendcmdpoll(priv, SD_ACMD41, MMCD_ACMD41_VOLTAGEWINDOW|sdcapacity);
|
||||
mmcsd_sendcmdpoll(priv, SD_ACMD41, MMCSD_ACMD41_VOLTAGEWINDOW|sdcapacity);
|
||||
ret = SDIO_RECVR3(priv->dev, SD_CMD55, &response);
|
||||
if (ret != OK)
|
||||
{
|
||||
@ -1155,7 +1497,7 @@ static inline int mmcsd_cardidentify(struct mmcsd_state_s *priv)
|
||||
* addressing
|
||||
*/
|
||||
|
||||
if ((response & MMCD_R3_HIGHCAPACITY) != 0)
|
||||
if ((response & MMCSD_R3_HIGHCAPACITY) != 0)
|
||||
{
|
||||
fvdbg("SD V2.x card with block addressing\n");
|
||||
DEBUGASSERT(priv->type == MMCSD_CARDTYPE_SDV2);
|
||||
@ -1243,6 +1585,15 @@ static inline int mmcsd_cardidentify(struct mmcsd_state_s *priv)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Verify that we are in IDLE state */
|
||||
|
||||
ret = mmcsd_verifyidle(priv);
|
||||
if (ret != OK)
|
||||
{
|
||||
fdbg("ERROR: Failed to enter IDLE state\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -1417,7 +1768,7 @@ static int mmcsd_hwinitialize(struct mmcsd_state_s *priv)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void mmcsd_hwuninitialize(struct mmcsd_state_s *priv)
|
||||
static void mmcsd_hwuninitialize(struct mmcsd_state_s *priv)
|
||||
{
|
||||
if (priv)
|
||||
{
|
||||
@ -1498,7 +1849,7 @@ int mmcsd_slotinitialize(int minor, int slotno, FAR struct sdio_dev_s *dev)
|
||||
else
|
||||
{
|
||||
fdbg("ERROR: Failed to initialize MMC/SD slot %d: %d\n",
|
||||
slotno, -ret);
|
||||
slotno, ret);
|
||||
goto errout_with_alloc;
|
||||
}
|
||||
}
|
||||
@ -1510,7 +1861,7 @@ int mmcsd_slotinitialize(int minor, int slotno, FAR struct sdio_dev_s *dev)
|
||||
ret = rwb_initialize(&priv->rwbuffer);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("ERROR: Buffer setup failed: %d\n", -ret);
|
||||
fdbg("ERROR: Buffer setup failed: %d\n", ret);
|
||||
goto errout_with_hwinit;
|
||||
}
|
||||
#endif
|
||||
@ -1524,7 +1875,7 @@ int mmcsd_slotinitialize(int minor, int slotno, FAR struct sdio_dev_s *dev)
|
||||
ret = register_blockdriver(devname, &g_bops, 0, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
fdbg("ERROR: register_blockdriver failed: %d\n", -ret);
|
||||
fdbg("ERROR: register_blockdriver failed: %d\n", ret);
|
||||
goto errout_with_buffers;
|
||||
}
|
||||
}
|
||||
|
@ -60,11 +60,21 @@
|
||||
#define MMCSD_CMD8ECHO_MASK (0xff << MMCSD_CMD8ECHO_SHIFT)
|
||||
# define MMCSD_CMD8CHECKPATTERN (0xaa << MMCSD_CMD8ECHO_SHIFT)
|
||||
|
||||
/* ACMD6 argument */
|
||||
|
||||
#define MMCSD_ACMD6_BUSWIDTH_1 (0) /* Bus width = 1-bit */
|
||||
#define MMCSD_ACMD6_BUSWIDTH_4 (2) /* Bus width = 4-bit */
|
||||
|
||||
/* ACMD41 argument */
|
||||
|
||||
#define MMCD_ACMD41_VOLTAGEWINDOW 0x80100000
|
||||
#define MMCD_ACMD41_HIGHCAPACITY (1 << 30)
|
||||
#define MMCD_ACMD41_STDCAPACITY (0)
|
||||
#define MMCSD_ACMD41_VOLTAGEWINDOW 0x80100000
|
||||
#define MMCSD_ACMD41_HIGHCAPACITY (1 << 30)
|
||||
#define MMCSD_ACMD41_STDCAPACITY (0)
|
||||
|
||||
/* ACMD42 argument */
|
||||
|
||||
#define MMCSD_ACMD42_CD_DISCONNECT (0) /* Disconnect card detection logic */
|
||||
#define MMCSD_ACMD42_CD_CONNECT (1) /* Connect card detection logic */
|
||||
|
||||
/* R1 Card Status bit definitions */
|
||||
|
||||
@ -135,9 +145,16 @@
|
||||
#define MMCSD_VDD_33_34 (1 << 21) /* VDD voltage 3.3-3.4 */
|
||||
#define MMCSD_VDD_34_35 (1 << 22) /* VDD voltage 3.4-3.5 */
|
||||
#define MMCSD_VDD_35_36 (1 << 23) /* VDD voltage 3.5-3.6 */
|
||||
#define MMCD_R3_HIGHCAPACITY (1 << 30) /* TRUE: Card supports block addressing */
|
||||
#define MMCSD_R3_HIGHCAPACITY (1 << 30) /* TRUE: Card supports block addressing */
|
||||
#define MMCSD_CARD_BUSY (1 << 31) /* Card power-up busy bit */
|
||||
|
||||
/* SD Configuration Register (SCR) encoding */
|
||||
|
||||
#define MMCSD_SCR_BUSWIDTH_1BIT (1)
|
||||
#define MMCSD_SCR_BUSWIDTH_2BIT (2)
|
||||
#define MMCSD_SCR_BUSWIDTH_4BIT (4)
|
||||
#define MMCSD_SCR_BUSWIDTH_8BIT (8)
|
||||
|
||||
/* Last 4 bytes of the 48-bit R7 response */
|
||||
|
||||
#define MMCSD_R7VERSION_SHIFT 28 /* Bits 28-31: Command version number */
|
||||
@ -153,7 +170,7 @@
|
||||
* Public Types
|
||||
********************************************************************************************/
|
||||
|
||||
/* Decoded CID register */
|
||||
/* Decoded Card Identification (CID) register */
|
||||
|
||||
struct mmcsd_cid_s
|
||||
{
|
||||
@ -168,7 +185,7 @@ struct mmcsd_cid_s
|
||||
/* 0:0 1-bit (not used) */
|
||||
};
|
||||
|
||||
/* Decoded CSD register */
|
||||
/* Decoded Card Specific Data (CSD) register */
|
||||
|
||||
struct mmcsd_csd_s
|
||||
{
|
||||
@ -264,6 +281,17 @@ struct mmcsd_csd_s
|
||||
/* 0:0 Not used */
|
||||
};
|
||||
|
||||
struct mmcsd_scr_s
|
||||
{
|
||||
ubyte scrversion; /* 63:60 Version of SCR structure */
|
||||
ubyte sdversion; /* 59:56 SD memory card physical layer version */
|
||||
ubyte erasestate; /* 55:55 Data state after erase (1 or 0) */
|
||||
ubyte security; /* 54:52 SD security support */
|
||||
ubyte buswidth; /* 51:48 DAT bus widthes supported */
|
||||
/* 47:32 SD reserved space */
|
||||
uint32 mfgdata; /* 31:0 Reserved for manufacturing data */
|
||||
};
|
||||
|
||||
/********************************************************************************************
|
||||
* Public Data
|
||||
********************************************************************************************/
|
||||
|
@ -359,25 +359,6 @@
|
||||
|
||||
#define SDIO_CLOCK(dev,rate) ((dev)->clock(dev,rate))
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_SETBLOCKLEN
|
||||
*
|
||||
* Description:
|
||||
* Set the MMC/SD block length and block count
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* blocklen - The block length
|
||||
* nblocks - The block count
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define SDIO_SETBLOCKLEN(dev,blocklen,nblocks) \
|
||||
((dev)->setblocklen(dev,blocklen,nblocks))
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_ATTACH
|
||||
*
|
||||
@ -413,6 +394,26 @@
|
||||
|
||||
#define SDIO_SENDCMD(dev,cmd,arg) ((dev)->sendcmd(dev,cmd,arg))
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_SENDSETUP
|
||||
*
|
||||
* Description:
|
||||
* Setup hardware in preparation for data trasfer from the card. This method
|
||||
* will do whatever controller setup is necessary. This would be called
|
||||
* for SD memory just AFTER sending CMD24 (WRITE_BLOCK), CMD25
|
||||
* (WRITE_MULTIPLE_BLOCK), ... and before SDIO_SENDDATA is called.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* nbytes - The number of bytes in the transfer
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes sent on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define SDIO_SENDSETUP(dev,nbytes) ((dev)->sendsetup(dev,nbytes))
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_SENDDATA
|
||||
*
|
||||
@ -424,7 +425,7 @@
|
||||
* data - Data to be sent
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes sent on succes; a negated errno on failure
|
||||
* Number of bytes sent on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -475,7 +476,28 @@
|
||||
#define SDIO_RECVR4(dev,cmd,R4) ((dev)->recvR4(dev,cmd,R4)) /* 48-bit */
|
||||
#define SDIO_RECVR5(dev,cmd,R5) ((dev)->recvR5(dev,cmd,R5)) /* 48-bit */
|
||||
#define SDIO_RECVR6(dev,cmd,R6) ((dev)->recvR6(dev,cmd,R6)) /* 48-bit */
|
||||
#define SDIO_RECVR7(dev,cmd,R7) ((dev)->recvR6(dev,cmd,R7)) /* 48-bit */
|
||||
#define SDIO_RECVR7(dev,cmd,R7) ((dev)->recvR7(dev,cmd,R7)) /* 48-bit */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_RECVSETUP
|
||||
*
|
||||
* Description:
|
||||
* Setup hardware in preparation for data trasfer from the card. This method
|
||||
* will do whatever controller setup is necessary. This would be called
|
||||
* for SD memory just BEFORE sending CMD13 (SEND_STATUS), CMD17
|
||||
* (READ_SINGLE_BLOCK), CMD18 (READ_MULTIPLE_BLOCKS), ACMD51 (SEND_SCR), ...
|
||||
* and before SDIO_RECVDATA is called.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* nbytes - The number of bytes in the transfer
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes sent on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define SDIO_RECVSETUP(dev,nbytes) ((dev)->recvsetup(dev,nbytes))
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_RECVDATA
|
||||
@ -488,7 +510,7 @@
|
||||
* buffer - Buffer in which to receive the data
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes sent on succes; a negated errno on failure
|
||||
* Number of bytes sent on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -502,18 +524,15 @@
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* eventset - A bitset of events to enable or disable (see SDIOEVENT_*
|
||||
* definitions
|
||||
* enable - TRUE: enable event; FALSE: disable events
|
||||
* eventset - A bitset of events to enable or disable (see MMCSDEVENT_*
|
||||
* definitions). 0=disable; 1=enable.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define SDIO_EVENTENABLE(dev,eventset) ((dev)->eventenable(dev,eventset,TRUE))
|
||||
#define SDIO_EVENTDISABLE(dev,eventset) ((dev)->eventenable(dev,eventset,FALSE))
|
||||
#define SDIO_EVENTDISABLEALL(dev) ((dev)->eventenable(dev,SDIOEVENT_ALLEVENTS,FALSE))
|
||||
#define SDIO_EVENTENABLE(dev,eventset) ((dev)->eventenable(dev,eventset))
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_EVENTWAIT
|
||||
@ -526,8 +545,9 @@
|
||||
* timeout - Maximum time in milliseconds to wait. Zero means no timeout.
|
||||
*
|
||||
* Returned Value:
|
||||
* Event set containing the event(s) that ended the wait. If no events the
|
||||
* Event set containing the event(s) that ended the wait. If no events the
|
||||
* returned event set is zero, then the wait was terminated by the timeout.
|
||||
* All events are cleared disabled after the wait concludes.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -538,13 +558,14 @@
|
||||
*
|
||||
* Description:
|
||||
* Return the current event set. This supports polling for MMC/SD (vs.
|
||||
* waiting).
|
||||
* waiting). Only enabled events need be reported.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
*
|
||||
* Returned Value:
|
||||
* Event set containing the current events (cleared after reading).
|
||||
* Event set containing the current events (All pending events are cleared
|
||||
* after reading).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -609,7 +630,7 @@
|
||||
* buffer - The memory to DMA from
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -630,7 +651,7 @@
|
||||
* buffer - The memory to DMA into
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -650,7 +671,7 @@
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -670,7 +691,7 @@
|
||||
* dev - An instance of the MMC/SD device interface
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -692,7 +713,7 @@
|
||||
* remaining in the transfer.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on succes; a negated errno on failure
|
||||
* OK on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -713,9 +734,16 @@ enum sdio_clock_e
|
||||
CLOCK_SDIO_DISABLED = 0, /* Clock is disabled */
|
||||
CLOCK_IDMODE, /* Initial ID mode clocking (<400KHz) */
|
||||
CLOCK_MMC_TRANSFER, /* MMC normal operation clocking */
|
||||
CLOCK_SD_TRANSFER /* SD normal operation clocking */
|
||||
CLOCK_SD_TRANSFER_1BIT, /* SD normal operation clocking (narrow 1-bit mode) */
|
||||
CLOCK_SD_TRANSFER_4BIT /* SD normal operation clocking (wide 4-bit mode) */
|
||||
};
|
||||
|
||||
/* Event set. A ubyte is big enough to hold a set of 8-events. If more are
|
||||
* needed, change this to a uint16.
|
||||
*/
|
||||
|
||||
typedef ubyte sdio_eventset_t;
|
||||
|
||||
/* This structure defines the interface between the NuttX MMC/SD
|
||||
* driver and the chip- or board-specific MMC/SD interface. This
|
||||
* interface is only used in architectures that support SDIO
|
||||
@ -736,12 +764,12 @@ struct sdio_dev_s
|
||||
ubyte (*status)(FAR struct sdio_dev_s *dev);
|
||||
void (*widebus)(FAR struct sdio_dev_s *dev, boolean enable);
|
||||
void (*clock)(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate);
|
||||
int (*setblocklen)(FAR struct sdio_dev_s *dev, int blocklen, int nblocks);
|
||||
int (*attach)(FAR struct sdio_dev_s *dev);
|
||||
|
||||
/* Command/Status/Data Transfer */
|
||||
|
||||
void (*sendcmd)(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 arg);
|
||||
int (*sendsetup)(FAR struct sdio_dev_s *dev, uint32 nbytes);
|
||||
int (*senddata)(FAR struct sdio_dev_s *dev, FAR const ubyte *buffer);
|
||||
|
||||
int (*waitresponse)(FAR struct sdio_dev_s *dev, uint32 cmd);
|
||||
@ -752,11 +780,12 @@ struct sdio_dev_s
|
||||
int (*recvR5)(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *R5);
|
||||
int (*recvR6)(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *R6);
|
||||
int (*recvR7)(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *R7);
|
||||
int (*recvsetup)(FAR struct sdio_dev_s *dev, uint32 nbytes);
|
||||
int (*recvdata)(FAR struct sdio_dev_s *dev, FAR ubyte *buffer);
|
||||
|
||||
/* EVENT handler */
|
||||
|
||||
void (*eventenable)(FAR struct sdio_dev_s *dev, ubyte eventset, boolean enable);
|
||||
void (*eventenable)(FAR struct sdio_dev_s *dev, sdio_eventset_t eventset);
|
||||
ubyte (*eventwait)(FAR struct sdio_dev_s *dev, uint32 timeout);
|
||||
ubyte (*events)(FAR struct sdio_dev_s *dev);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user