Skip to content

Commit

Permalink
mmcsd: make a compatibility change for cmd12 and cmd23
Browse files Browse the repository at this point in the history
For some sd cards don't support cmd23 or support cmd23 indicated by
bit33 in scr

Signed-off-by: wanggang26 <[email protected]>
  • Loading branch information
wanggang26 committed Sep 17, 2024
1 parent 263f895 commit 52418ac
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 17 deletions.
1 change: 1 addition & 0 deletions drivers/mmcsd/mmcsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct mmcsd_state_s
uint8_t mode:4; /* (See MMCSDMODE_* definitions) */
uint8_t type:4; /* Card type (See MMCSD_CARDTYPE_* definitions) */
uint8_t buswidth:4; /* Bus widths supported (SD only) */
uint8_t cmd23support:1; /* CMD23 supported (SD only) */
sdio_capset_t caps; /* SDIO driver capabilities/limitations */
uint32_t cid[4]; /* CID register */
uint32_t csd[4]; /* CSD register */
Expand Down
101 changes: 84 additions & 17 deletions drivers/mmcsd/mmcsd_sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ static int mmcsd_stoptransmission(FAR struct mmcsd_state_s *priv);
#endif
static int mmcsd_setblocklen(FAR struct mmcsd_state_s *priv,
uint32_t blocklen);
static int mmcsd_setblockcount(FAR struct mmcsd_state_s *priv,
uint32_t nblocks);
static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv,
FAR uint8_t *buffer, off_t startblock);
#if MMCSD_MULTIBLOCK_LIMIT != 1
Expand Down Expand Up @@ -956,13 +958,16 @@ static void mmcsd_decode_scr(FAR struct mmcsd_state_s *priv, uint32_t scr[2])
* 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
* Reserved 47:34 14-bit SD reserved space
* CMD_SUPPORT 33:32 2-bit command supported (bit33 for cmd23)
*/

#ifdef CONFIG_ENDIAN_BIG /* Card transfers SCR in big-endian order */
priv->buswidth = (scr[0] >> 16) & 15;
priv->cmd23support = scr[0] & 2;
#else
priv->buswidth = (scr[0] >> 8) & 15;
priv->buswidth = (scr[0] >> 8) & 15;
priv->cmd23support = (scr[0] >> 24) & 2;
#endif

#ifdef CONFIG_DEBUG_FS_INFO
Expand Down Expand Up @@ -1386,6 +1391,29 @@ static int mmcsd_setblocklen(FAR struct mmcsd_state_s *priv,
return ret;
}

/****************************************************************************
* Name: mmcsd_setblockcount
*
* Description:
* Set the block counts.
*
****************************************************************************/

static int mmcsd_setblockcount(FAR struct mmcsd_state_s *priv,
uint32_t nblocks)
{
int ret;

mmcsd_sendcmdpoll(priv, MMCSD_CMD23, nblocks);
ret = mmcsd_recv_r1(priv, MMCSD_CMD23);
if (ret != OK)
{
ferr("ERROR: mmcsd_recv_r1 for CMD23 failed: %d\n", ret);
}

return ret;
}

/****************************************************************************
* Name: mmcsd_readsingle
*
Expand Down Expand Up @@ -1625,6 +1653,19 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
SDIO_RECVSETUP(priv->dev, buffer, nbytes);
}

#ifdef CONFIG_MMCSD_MMCSUPPORT
if (IS_MMC(priv->type) || (IS_SD(priv->type) && priv->cmd23support))
#else
if (IS_SD(priv->type) && priv->cmd23support)
#endif
{
ret = mmcsd_setblockcount(priv, nblocks);
if (ret != OK)
{
return ret;
}
}

/* Send CMD18, READ_MULT_BLOCK: Read a block of the size selected by
* the mmcsd_setblocklen() and verify that good R1 status is returned
*/
Expand All @@ -1647,13 +1688,16 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
return ret;
}

/* Send STOP_TRANSMISSION */
if (IS_SD(priv->type) && !priv->cmd23support)
{
/* Send STOP_TRANSMISSION */

ret = mmcsd_stoptransmission(priv);
ret = mmcsd_stoptransmission(priv);

if (ret != OK)
{
ferr("ERROR: mmcsd_stoptransmission failed: %d\n", ret);
if (ret != OK)
{
ferr("ERROR: mmcsd_stoptransmission failed: %d\n", ret);
}
}

/* On success, return the number of blocks read */
Expand Down Expand Up @@ -1946,6 +1990,19 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
}
}

#ifdef CONFIG_MMCSD_MMCSUPPORT
if (IS_MMC(priv->type) || (IS_SD(priv->type) && priv->cmd23support))
#else
if (IS_SD(priv->type) && priv->cmd23support)
#endif
{
ret = mmcsd_setblockcount(priv, nblocks);
if (ret != OK)
{
return ret;
}
}

/* If Controller does not need DMA setup before the write then send CMD25
* now.
*/
Expand Down Expand Up @@ -1978,7 +2035,7 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
ret = SDIO_DMASENDSETUP(priv->dev, buffer, nbytes);
if (ret != OK)
{
finfo("SDIO_DMASENDSETUP: error %d\n", ret);
ferr("SDIO_DMASENDSETUP: error %d\n", ret);
SDIO_CANCEL(priv->dev);
return ret;
}
Expand Down Expand Up @@ -2021,18 +2078,28 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
*/
}

/* Send STOP_TRANSMISSION */

ret = mmcsd_stoptransmission(priv);
if (evret != OK)
if (IS_SD(priv->type) && !priv->cmd23support)
{
return evret;
}
/* Send STOP_TRANSMISSION */

if (ret != OK)
ret = mmcsd_stoptransmission(priv);
if (evret != OK)
{
return evret;
}

if (ret != OK)
{
ferr("ERROR: mmcsd_stoptransmission failed: %d\n", ret);
return ret;
}
}
else
{
ferr("ERROR: mmcsd_stoptransmission failed: %d\n", ret);
return ret;
if (evret != OK)
{
return evret;
}
}

/* Flag that a write transfer is pending that we will have to check for
Expand Down

0 comments on commit 52418ac

Please sign in to comment.