diff options
Diffstat (limited to 'nuttx/drivers')
-rw-r--r-- | nuttx/drivers/mmcsd/mmcsd_sdio.c | 268 |
1 files changed, 135 insertions, 133 deletions
diff --git a/nuttx/drivers/mmcsd/mmcsd_sdio.c b/nuttx/drivers/mmcsd/mmcsd_sdio.c index 1a3016e88..97c2a6dc0 100644 --- a/nuttx/drivers/mmcsd/mmcsd_sdio.c +++ b/nuttx/drivers/mmcsd/mmcsd_sdio.c @@ -944,13 +944,13 @@ static int mmcsd_verifystate(FAR struct mmcsd_state_s *priv, uint32 state) * Transfer Helpers ****************************************************************************/ -/****************************************************************************
- * Name: mmcsd_wrprotected
- *
- * Description:
+/**************************************************************************** + * Name: mmcsd_wrprotected + * + * Description: * Return true if the the card is unlocked an not write protected. The - *
- *
+ * + * ****************************************************************************/ static boolean mmcsd_wrprotected(FAR struct mmcsd_state_s *priv) @@ -964,12 +964,12 @@ static boolean mmcsd_wrprotected(FAR struct mmcsd_state_s *priv) return (priv->wrprotect || priv->locked || SDIO_WRPROTECTED(priv->dev)); } -/****************************************************************************
- * Name: mmcsd_eventwait
- *
- * Description:
- * Wait for the specified events to occur. Check for wakeup on error events.
- *
+/**************************************************************************** + * Name: mmcsd_eventwait + * + * Description: + * Wait for the specified events to occur. Check for wakeup on error events. + * ****************************************************************************/ static int mmcsd_eventwait(FAR struct mmcsd_state_s *priv, @@ -1001,14 +1001,14 @@ static int mmcsd_eventwait(FAR struct mmcsd_state_s *priv, return OK; } -/****************************************************************************
- * Name: mmcsd_transferready
- *
- * Description:
+/**************************************************************************** + * Name: mmcsd_transferready + * + * Description: * Check if the MMC/SD card is ready for the next read or write transfer. * Ready means: (1) card still in the slot, and (2) if the last transfer - * was a write transfer, the card is no longer busy from that transfer.
- *
+ * was a write transfer, the card is no longer busy from that transfer. + * ****************************************************************************/ static int mmcsd_transferready(FAR struct mmcsd_state_s *priv) @@ -1095,27 +1095,27 @@ static int mmcsd_transferready(FAR struct mmcsd_state_s *priv) return -ETIMEDOUT; } -/****************************************************************************
- * Name: mmcsd_stoptransmission
- *
- * Description:
- * Send STOP_TRANSMISSION
- *
+/**************************************************************************** + * Name: mmcsd_stoptransmission + * + * Description: + * Send STOP_TRANSMISSION + * ****************************************************************************/ -
+ static int mmcsd_stoptransmission(FAR struct mmcsd_state_s *priv) { - int ret;
-
- /* Send CMD12, STOP_TRANSMISSION, and verify good R1 return status */
+ int ret; + + /* Send CMD12, STOP_TRANSMISSION, and verify good R1 return status */ - mmcsd_sendcmdpoll(priv, MMCSD_CMD12, 0);
+ mmcsd_sendcmdpoll(priv, MMCSD_CMD12, 0); ret = mmcsd_recvR1(priv, MMCSD_CMD12); if (ret != OK) { fdbg("ERROR: mmcsd_recvR1 for CMD12 failed: %d\n", ret); - }
- return ret;
+ } + return ret; } /**************************************************************************** @@ -1139,16 +1139,16 @@ static int mmcsd_setblocklen(FAR struct mmcsd_state_s *priv, uint32 blocklen) * block length is specified in the CSD. */ - mmcsd_sendcmdpoll(priv, MMCSD_CMD16, priv->blocksize);
- ret = mmcsd_recvR1(priv, MMCSD_CMD16);
- if (ret == OK)
+ mmcsd_sendcmdpoll(priv, MMCSD_CMD16, priv->blocksize); + ret = mmcsd_recvR1(priv, MMCSD_CMD16); + if (ret == OK) { priv->selblocklen = blocklen; } else { - fdbg("ERROR: mmcsd_recvR1 for CMD16 failed: %d\n", ret);
- }
+ fdbg("ERROR: mmcsd_recvR1 for CMD16 failed: %d\n", ret); + } } return ret; @@ -1172,12 +1172,12 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, DEBUGASSERT(priv != NULL && buffer != NULL); /* Check if the card is locked */ -
- if (priv->locked)
+ + if (priv->locked) { - fdbg("ERROR: Card is locked\n");
- return -EPERM;
- }
+ fdbg("ERROR: Card is locked\n"); + return -EPERM; + } /* Verify that the card is ready for the transfer. The card may still be * busy from the preceding write transfer. It would be simpler to check @@ -1207,28 +1207,28 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, } fvdbg("offset=%d\n", offset); - /* Select the block size for the card */
+ /* Select the block size for the card */ ret = mmcsd_setblocklen(priv, priv->blocksize); - if (ret != OK)
+ if (ret != OK) { - fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret);
- return ret;
- }
+ fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret); + return ret; + } /* Configure SDIO controller hardware for the read transfer */ SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); -#ifdef CONFIG_SDIO_DMA
+#ifdef CONFIG_SDIO_DMA if (priv->dma) - {
+ { SDIO_DMARECVSETUP(priv->dev, buffer, priv->blocksize); } else -#endif
- {
+#endif + { SDIO_RECVSETUP(priv->dev, buffer, priv->blocksize); - }
+ } /* Send CMD17, READ_SINGLE_BLOCK: Read a block of the size selected * by the mmcsd_setblocklen() and verify that good R1 status is @@ -1236,19 +1236,19 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, * state. */ - mmcsd_sendcmdpoll(priv, MMCSD_CMD17, offset);
- ret = mmcsd_recvR1(priv, MMCSD_CMD17);
- if (ret != OK)
- {
+ mmcsd_sendcmdpoll(priv, MMCSD_CMD17, offset); + ret = mmcsd_recvR1(priv, MMCSD_CMD17); + if (ret != OK) + { fdbg("ERROR: mmcsd_recvR1 for CMD17 failed: %d\n", ret); - return ret;
+ return ret; } /* Then wait for the data transfer to complete */ - ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, MMCSD_BLOCK_DATADELAY);
- if (ret != OK)
- {
+ ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, MMCSD_BLOCK_DATADELAY); + if (ret != OK) + { fdbg("ERROR: CMD17 transfer failed: %d\n", ret); } return ret; @@ -1274,12 +1274,12 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, DEBUGASSERT(priv != NULL && buffer != NULL && nblocks > 1); /* Check if the card is locked */ -
- if (priv->locked)
+ + if (priv->locked) { - fdbg("ERROR: Card is locked\n");
- return -EPERM;
- }
+ fdbg("ERROR: Card is locked\n"); + return -EPERM; + } /* Verify that the card is ready for the transfer. The card may still be * busy from the preceding write transfer. It would be simpler to check @@ -1310,48 +1310,48 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, } fvdbg("nbytes=%d byte offset=%d\n", nbytes, offset); - /* Select the block size for the card */
+ /* Select the block size for the card */ ret = mmcsd_setblocklen(priv, priv->blocksize); - if (ret != OK)
+ if (ret != OK) { - fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret);
- return ret;
- }
+ fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret); + return ret; + } /* Configure SDIO controller hardware for the read transfer */ SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); -#ifdef CONFIG_SDIO_DMA
+#ifdef CONFIG_SDIO_DMA if (priv->dma) - {
+ { SDIO_DMARECVSETUP(priv->dev, buffer, nbytes); } else -#endif
- {
+#endif + { SDIO_RECVSETUP(priv->dev, buffer, nbytes); - }
-
+ } + /* Send CMD18, READ_MULT_BLOCK: Read a block of the size selected by * the mmcsd_setblocklen() and verify that good R1 status is returned */ mmcsd_sendcmdpoll(priv, MMCSD_CMD18, offset); ret = mmcsd_recvR1(priv, MMCSD_CMD18); - if (ret != OK)
- {
+ if (ret != OK) + { fdbg("ERROR: mmcsd_recvR1 for CMD18 failed: %d\n", ret); - return ret;
+ return ret; } /* Wait for the transfer to complete */ ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, nblocks * MMCSD_BLOCK_DATADELAY); - if (ret != OK)
- {
+ if (ret != OK) + { fdbg("ERROR: CMD18 transfer failed: %d\n", ret); - return ret;
+ return ret; } /* Send STOP_TRANSMISSION */ @@ -1414,12 +1414,12 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, /* Check if the card is locked or write protected (either via software or * via the mechanical write protect on the card) */ -
- if (mmcsd_wrprotected(priv))
+ + if (mmcsd_wrprotected(priv)) { - fdbg("ERROR: Card is locked or write protected\n");
- return -EPERM;
- }
+ fdbg("ERROR: Card is locked or write protected\n"); + return -EPERM; + } /* Verify that the card is ready for the transfer. The card may still be * busy from the preceding write transfer. It would be simpler to check @@ -1449,13 +1449,13 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, } fvdbg("offset=%d\n", offset); - /* Select the block size for the card */
+ /* Select the block size for the card */ ret = mmcsd_setblocklen(priv, priv->blocksize); - if (ret != OK)
+ if (ret != OK) { - fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret);
- return ret;
+ fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret); + return ret; } /* Send CMD24, WRITE_BLOCK, and verify that good R1 status is returned */ @@ -1464,29 +1464,29 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, ret = mmcsd_recvR1(priv, MMCSD_CMD24); if (ret != OK) { - fdbg("ERROR: mmcsd_recvR1 for CMD24 failed: %d\n", ret);
- return ret;
+ fdbg("ERROR: mmcsd_recvR1 for CMD24 failed: %d\n", ret); + return ret; } -
+ /* Configure SDIO controller hardware for the write transfer */ SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); -#ifdef CONFIG_SDIO_DMA
+#ifdef CONFIG_SDIO_DMA if (priv->dma) - {
- SDIO_DMASENDSETUP(priv->dev, buffer, priv->blocksize);
+ { + SDIO_DMASENDSETUP(priv->dev, buffer, priv->blocksize); } else -#endif
- {
- SDIO_SENDSETUP(priv->dev, buffer, priv->blocksize);
- }
+#endif + { + SDIO_SENDSETUP(priv->dev, buffer, priv->blocksize); + } /* Wait for the transfer to complete */ - ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, MMCSD_BLOCK_DATADELAY);
- if (ret != OK)
- {
+ ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, MMCSD_BLOCK_DATADELAY); + if (ret != OK) + { fdbg("ERROR: CMD24 transfer failed: %d\n", ret); } @@ -1520,12 +1520,12 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, /* Check if the card is locked or write protected (either via software or * via the mechanical write protect on the card) */ -
- if (mmcsd_wrprotected(priv))
+ + if (mmcsd_wrprotected(priv)) { - fdbg("ERROR: Card is locked or write protected\n");
- return -EPERM;
- }
+ fdbg("ERROR: Card is locked or write protected\n"); + return -EPERM; + } /* Verify that the card is ready for the transfer. The card may still be * busy from the preceding write transfer. It would be simpler to check @@ -1556,13 +1556,13 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, } fvdbg("nbytes=%d byte offset=%d\n", nbytes, offset); - /* Select the block size for the card */
+ /* Select the block size for the card */ ret = mmcsd_setblocklen(priv, priv->blocksize); - if (ret != OK)
+ if (ret != OK) { - fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret);
- return ret;
+ fdbg("ERROR: mmcsd_setblocklen failed: %d\n", ret); + return ret; } /* If this is an SD card, then send ACMD23 (SET_WR_BLK_COUNT) just before @@ -1573,14 +1573,14 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, if (IS_SD(priv->type)) { - /* Send CMD55, APP_CMD, a verify that good R1 status is retured */
-
+ /* Send CMD55, APP_CMD, a verify that good R1 status is retured */ + mmcsd_sendcmdpoll(priv, SD_CMD55, 0); ret = mmcsd_recvR1(priv, SD_CMD55); if (ret != OK) { - fdbg("ERROR: mmcsd_recvR1 for CMD55 (ACMD23) failed: %d\n", ret);
- return ret;
+ fdbg("ERROR: mmcsd_recvR1 for CMD55 (ACMD23) failed: %d\n", ret); + return ret; } /* Send CMD23, SET_WR_BLK_COUNT, and verify that good R1 status is returned */ @@ -1589,8 +1589,8 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, ret = mmcsd_recvR1(priv, SD_ACMD23); if (ret != OK) { - fdbg("ERROR: mmcsd_recvR1 for ACMD23 failed: %d\n", ret);
- return ret;
+ fdbg("ERROR: mmcsd_recvR1 for ACMD23 failed: %d\n", ret); + return ret; } } @@ -1602,31 +1602,31 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, ret = mmcsd_recvR1(priv, MMCSD_CMD25); if (ret != OK) { - fdbg("ERROR: mmcsd_recvR1 for CMD24 failed: %d\n", ret);
- return ret;
+ fdbg("ERROR: mmcsd_recvR1 for CMD24 failed: %d\n", ret); + return ret; } -
+ /* Configure SDIO controller hardware for the write transfer */ SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT); -#ifdef CONFIG_SDIO_DMA
+#ifdef CONFIG_SDIO_DMA if (priv->dma) - {
- SDIO_DMASENDSETUP(priv->dev, buffer, nbytes);
+ { + SDIO_DMASENDSETUP(priv->dev, buffer, nbytes); } else -#endif
- {
- SDIO_SENDSETUP(priv->dev, buffer, nbytes);
- }
+#endif + { + SDIO_SENDSETUP(priv->dev, buffer, nbytes); + } /* Wait for the transfer to complete */ ret =mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT, nblocks * MMCSD_BLOCK_DATADELAY); - if (ret != OK)
- {
+ if (ret != OK) + { fdbg("ERROR: CMD18 transfer failed: %d\n", ret); - return ret;
+ return ret; } /* Send STOP_TRANSMISSION */ @@ -1951,7 +1951,8 @@ static void mmcsd_mediachange(FAR void *arg) if (SDIO_PRESENT(priv->dev)) { /* No... process the card insertion. This could cause chaos if we think - * that a card is already present and there are mounted filesystms! + * that a card is already present and there are mounted filesystems! + * NOTE that mmcsd_probe() will always re-enable callbacks appropriately. */ (void)mmcsd_probe(priv); @@ -1959,7 +1960,8 @@ static void mmcsd_mediachange(FAR void *arg) else { /* No... process the card removal. This could have very bad implications - * for any mounted file systems! + * for any mounted file systems! NOTE that mmcsd_removed() does NOT + * re-enable callbacks so we will need to do that here. */ (void)mmcsd_removed(priv); |