mmcsd: make a compatibility change for cmd12 and cmd23

For some sd cards don't support cmd23 or support cmd23 indicated by
bit33 in scr

Signed-off-by: wanggang26 <wanggang26@xiaomi.com>
This commit is contained in:
wanggang26 2024-09-16 15:14:07 +08:00 committed by Xiang Xiao
parent 395c449884
commit ff0194fb74
2 changed files with 86 additions and 18 deletions

View file

@ -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 */

View file

@ -164,6 +164,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
@ -973,13 +975,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
@ -1403,6 +1408,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
*
@ -1642,6 +1670,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
*/
@ -1664,13 +1705,16 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
return ret;
}
/* Send STOP_TRANSMISSION */
ret = mmcsd_stoptransmission(priv);
if (ret != OK)
if (IS_SD(priv->type) && !priv->cmd23support)
{
ferr("ERROR: mmcsd_stoptransmission failed: %d\n", ret);
/* Send STOP_TRANSMISSION */
ret = mmcsd_stoptransmission(priv);
if (ret != OK)
{
ferr("ERROR: mmcsd_stoptransmission failed: %d\n", ret);
}
}
/* On success, return the number of blocks read */
@ -1963,6 +2007,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.
*/
@ -1995,7 +2052,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;
}
@ -2038,18 +2095,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 */
ret = mmcsd_stoptransmission(priv);
if (evret != OK)
{
return evret;
}
if (ret != OK)
{
ferr("ERROR: mmcsd_stoptransmission failed: %d\n", ret);
return ret;
}
}
if (ret != OK)
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