mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 14:27:37 +08:00
SAMA5D HSMCI: Add method to do RX transfer without DMA. The 8-byte SCR transfer was failing silently with the DMA transfer, leaving the SD card in single bit mode
This commit is contained in:
+200
-64
@@ -185,6 +185,7 @@
|
|||||||
* I don't have any clue why at the moment. This option suppresses TX DMA (only).
|
* I don't have any clue why at the moment. This option suppresses TX DMA (only).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#undef HSCMI_NORXDMA
|
||||||
#define HSCMI_NOTXDMA 1
|
#define HSCMI_NOTXDMA 1
|
||||||
|
|
||||||
/* Timing */
|
/* Timing */
|
||||||
@@ -264,7 +265,7 @@
|
|||||||
#define HSMCI_DATA_TIMEOUT_ERRORS \
|
#define HSMCI_DATA_TIMEOUT_ERRORS \
|
||||||
( HSMCI_INT_CSTOE | HSMCI_INT_DTOE )
|
( HSMCI_INT_CSTOE | HSMCI_INT_DTOE )
|
||||||
|
|
||||||
#define HSMCI_DATA_DMARECV_ERRORS \
|
#define HSMCI_DATA_RECV_ERRORS \
|
||||||
( HSMCI_INT_OVRE | HSMCI_INT_BLKOVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | \
|
( HSMCI_INT_OVRE | HSMCI_INT_BLKOVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | \
|
||||||
HSMCI_INT_DCRCE )
|
HSMCI_INT_DCRCE )
|
||||||
|
|
||||||
@@ -285,8 +286,10 @@
|
|||||||
* 1: DMA buffer transfer has completed.
|
* 1: DMA buffer transfer has completed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define HSMCI_RECV_INTS \
|
||||||
|
( HSMCI_DATA_RECV_ERRORS | HSMCI_INT_RXRDY)
|
||||||
#define HSMCI_DMARECV_INTS \
|
#define HSMCI_DMARECV_INTS \
|
||||||
( HSMCI_DATA_DMARECV_ERRORS | HSMCI_INT_XFRDONE /* | HSMCI_INT_DMADONE */ )
|
( HSMCI_DATA_RECV_ERRORS | HSMCI_INT_XFRDONE /* | HSMCI_INT_DMADONE */ )
|
||||||
#define HSMCI_DMASEND_INTS \
|
#define HSMCI_DMASEND_INTS \
|
||||||
( HSMCI_DATA_DMASEND_ERRORS | HSMCI_INT_XFRDONE /* | HSMCI_INT_DMADONE */ )
|
( HSMCI_DATA_DMASEND_ERRORS | HSMCI_INT_XFRDONE /* | HSMCI_INT_DMADONE */ )
|
||||||
|
|
||||||
@@ -405,6 +408,11 @@ struct sam_dev_s
|
|||||||
|
|
||||||
uint32_t xfrmask; /* Interrupt enables for data transfer */
|
uint32_t xfrmask; /* Interrupt enables for data transfer */
|
||||||
|
|
||||||
|
/* Interrupt mode data transfer support */
|
||||||
|
|
||||||
|
uint32_t *buffer; /* Address of current R/W buffer */
|
||||||
|
ssize_t remaining; /* Number of bytes remaining in the transfer */
|
||||||
|
|
||||||
/* DMA data transfer support */
|
/* DMA data transfer support */
|
||||||
|
|
||||||
bool widebus; /* Required for DMA support */
|
bool widebus; /* Required for DMA support */
|
||||||
@@ -542,6 +550,10 @@ static int sam_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
|||||||
uint32_t arg);
|
uint32_t arg);
|
||||||
static void sam_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
|
static void sam_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
|
||||||
unsigned int nblocks);
|
unsigned int nblocks);
|
||||||
|
static int sam_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||||
|
size_t nbytes);
|
||||||
|
static int sam_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer,
|
||||||
|
size_t nbytes);
|
||||||
static int sam_cancel(FAR struct sdio_dev_s *dev);
|
static int sam_cancel(FAR struct sdio_dev_s *dev);
|
||||||
static int sam_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd);
|
static int sam_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd);
|
||||||
static int sam_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
static int sam_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||||
@@ -567,10 +579,14 @@ static int sam_registercallback(FAR struct sdio_dev_s *dev,
|
|||||||
#ifdef CONFIG_SDIO_DMA
|
#ifdef CONFIG_SDIO_DMA
|
||||||
static bool sam_dmasupported(FAR struct sdio_dev_s *dev);
|
static bool sam_dmasupported(FAR struct sdio_dev_s *dev);
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef HSCMI_NORXDMA
|
||||||
static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev,
|
static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev,
|
||||||
FAR uint8_t *buffer, size_t buflen);
|
FAR uint8_t *buffer, size_t buflen);
|
||||||
|
#endif
|
||||||
|
#ifndef HSCMI_NOTXDMA
|
||||||
static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
|
static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
|
||||||
FAR const uint8_t *buffer, size_t buflen);
|
FAR const uint8_t *buffer, size_t buflen);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Initialization/uninitialization/reset ************************************/
|
/* Initialization/uninitialization/reset ************************************/
|
||||||
|
|
||||||
@@ -590,8 +606,8 @@ static const struct sdio_dev_s g_callbacks =
|
|||||||
.attach = sam_attach,
|
.attach = sam_attach,
|
||||||
.sendcmd = sam_sendcmd,
|
.sendcmd = sam_sendcmd,
|
||||||
.blocksetup = sam_blocksetup,
|
.blocksetup = sam_blocksetup,
|
||||||
.recvsetup = sam_dmarecvsetup,
|
.recvsetup = sam_recvsetup,
|
||||||
.sendsetup = sam_dmasendsetup,
|
.sendsetup = sam_sendsetup,
|
||||||
.cancel = sam_cancel,
|
.cancel = sam_cancel,
|
||||||
.waitresponse = sam_waitresponse,
|
.waitresponse = sam_waitresponse,
|
||||||
.recvR1 = sam_recvshort,
|
.recvR1 = sam_recvshort,
|
||||||
@@ -607,8 +623,16 @@ static const struct sdio_dev_s g_callbacks =
|
|||||||
.registercallback = sam_registercallback,
|
.registercallback = sam_registercallback,
|
||||||
#ifdef CONFIG_SDIO_DMA
|
#ifdef CONFIG_SDIO_DMA
|
||||||
.dmasupported = sam_dmasupported,
|
.dmasupported = sam_dmasupported,
|
||||||
|
#ifndef HSCMI_NORXDMA
|
||||||
.dmarecvsetup = sam_dmarecvsetup,
|
.dmarecvsetup = sam_dmarecvsetup,
|
||||||
|
#else
|
||||||
|
.dmarecvsetup = sam_recvsetup,
|
||||||
|
#endif
|
||||||
|
#ifndef HSCMI_NOTXDMA
|
||||||
.dmasendsetup = sam_dmasendsetup,
|
.dmasendsetup = sam_dmasendsetup,
|
||||||
|
#else
|
||||||
|
.dmasendsetup = sam_sendsetup,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1498,12 +1522,12 @@ static int sam_hsmci_interrupt(struct sam_dev_s *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle in progress, interrupt driven data transfers ****************/
|
/* Handle in progress, interrupt driven data transfers ****************/
|
||||||
/* Do any of these interrupts signal the end a data transfer? */
|
/* Do any of these interrupts signal a data transfer event? */
|
||||||
|
|
||||||
pending = enabled & priv->xfrmask;
|
pending = enabled & priv->xfrmask;
|
||||||
if (pending != 0)
|
if (pending != 0)
|
||||||
{
|
{
|
||||||
/* Yes.. the transfer is complete. Did it complete with an error? */
|
/* Yes.. Did the transfer complete with an error? */
|
||||||
|
|
||||||
if ((pending & HSMCI_DATA_ERRORS) != 0)
|
if ((pending & HSMCI_DATA_ERRORS) != 0)
|
||||||
{
|
{
|
||||||
@@ -1523,9 +1547,40 @@ static int sam_hsmci_interrupt(struct sam_dev_s *priv)
|
|||||||
sam_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
|
sam_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No, If RXRDY is enabled, then we are doing a non-DMA receive.
|
||||||
|
* We need to transfer word(s) from the RDR register to the user
|
||||||
|
* buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
else if ((pending & HSMCI_INT_RXRDY) != 0)
|
||||||
|
{
|
||||||
|
/* Interrupt mode data transfer support */
|
||||||
|
|
||||||
|
DEBUGASSERT(!priv->dmabusy && priv->xfrbusy && !priv->txbusy);
|
||||||
|
DEBUGASSERT(priv->buffer && priv->remaining > 0);
|
||||||
|
|
||||||
|
*priv->buffer++ = sam_getreg(priv, SAM_HSMCI_RDR_OFFSET);
|
||||||
|
priv->remaining -= sizeof(uint32_t);
|
||||||
|
|
||||||
|
/* Are we finished? */
|
||||||
|
|
||||||
|
if (priv->remaining <= 0)
|
||||||
|
{
|
||||||
|
/* Yes.. End the transfer */
|
||||||
|
|
||||||
|
priv->buffer = NULL;
|
||||||
|
priv->remaining = 0;
|
||||||
|
|
||||||
|
sam_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise it must be a DMA transfer that completed successfully */
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No.. Then the transfer must have completed successfully */
|
/* End the transfer */
|
||||||
|
|
||||||
sam_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
|
sam_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
|
||||||
}
|
}
|
||||||
@@ -2076,6 +2131,138 @@ static void sam_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
|
|||||||
sam_putreg(priv, regval, SAM_HSMCI_BLKR_OFFSET);
|
sam_putreg(priv, regval, SAM_HSMCI_BLKR_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sam_recvsetup
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Setup hardware in preparation for data transfer from the card in non-DMA
|
||||||
|
* (interrupt driven mode). 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), etc. Normally, SDIO_WAITEVENT
|
||||||
|
* will be called to receive the indication that the transfer is complete.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - An instance of the SDIO device interface
|
||||||
|
* buffer - Address of the buffer in which to receive the data
|
||||||
|
* buflen - The number of bytes in the transfer
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Number of bytes sent on success; a negated errno on failure
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int sam_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||||
|
size_t buflen)
|
||||||
|
{
|
||||||
|
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||||
|
|
||||||
|
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
|
||||||
|
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
|
||||||
|
|
||||||
|
/* Initialize register sampling */
|
||||||
|
|
||||||
|
sam_xfrsampleinit(priv);
|
||||||
|
sam_xfrsample(priv, SAMPLENDX_BEFORE_SETUP);
|
||||||
|
|
||||||
|
/* Disable DMA handshaking */
|
||||||
|
|
||||||
|
sam_putreg(priv, 0, SAM_HSMCI_DMA_OFFSET);
|
||||||
|
|
||||||
|
/* Setup of the transfer configuration */
|
||||||
|
|
||||||
|
priv->dmabusy = false;
|
||||||
|
priv->xfrbusy = true;
|
||||||
|
priv->txbusy = false;
|
||||||
|
|
||||||
|
/* Save the destination buffer information for use by the interrupt handler */
|
||||||
|
|
||||||
|
priv->buffer = (uint32_t*)buffer;
|
||||||
|
priv->remaining = buflen;
|
||||||
|
|
||||||
|
/* And enable interrupts */
|
||||||
|
|
||||||
|
sam_configxfrints(priv, HSMCI_RECV_INTS);
|
||||||
|
sam_xfrsample(priv, SAMPLENDX_AFTER_SETUP);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sam_sendsetup
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Setup hardware in preparation for data transfer 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 SDIO device interface
|
||||||
|
* buffer - Address of the buffer containing the data to send
|
||||||
|
* buflen - The number of bytes in the transfer
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Number of bytes sent on success; a negated errno on failure
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int sam_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer,
|
||||||
|
size_t buflen)
|
||||||
|
{
|
||||||
|
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||||
|
unsigned int nwords;
|
||||||
|
const uint32_t *ptr;
|
||||||
|
uint32_t sr;
|
||||||
|
|
||||||
|
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
|
||||||
|
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
|
||||||
|
|
||||||
|
/* Disable DMA handshaking */
|
||||||
|
|
||||||
|
sam_putreg(priv, 0, SAM_HSMCI_DMA_OFFSET);
|
||||||
|
sam_configxfrints(priv, HSMCI_DMASEND_INTS);
|
||||||
|
|
||||||
|
priv->dmabusy = false;
|
||||||
|
priv->xfrbusy = true;
|
||||||
|
priv->txbusy = true;
|
||||||
|
|
||||||
|
/* Nullify register sampling */
|
||||||
|
|
||||||
|
sam_xfrsampleinit(priv);
|
||||||
|
|
||||||
|
/* Copy each word to the TX FIFO
|
||||||
|
*
|
||||||
|
* REVISIT: If TX data underruns occur, then it may be necessary to
|
||||||
|
* disable pre-emption around this loop.
|
||||||
|
*/
|
||||||
|
|
||||||
|
nwords = (buflen + 3) >> 2;
|
||||||
|
ptr = (const uint32_t *)buffer;
|
||||||
|
|
||||||
|
while (nwords > 0)
|
||||||
|
{
|
||||||
|
/* Check the HSMCI status */
|
||||||
|
|
||||||
|
sr = sam_getreg(priv, SAM_HSMCI_SR_OFFSET);
|
||||||
|
if ((sr & HSMCI_DATA_DMASEND_ERRORS) != 0)
|
||||||
|
{
|
||||||
|
/* Some fatal error has occurred */
|
||||||
|
|
||||||
|
fdbg("ERROR: sr %08x\n", sr);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
else if ((sr & HSMCI_INT_TXRDY) != 0)
|
||||||
|
{
|
||||||
|
/* TXRDY -- transfer another word */
|
||||||
|
|
||||||
|
sam_putreg(priv, *ptr++, SAM_HSMCI_TDR_OFFSET);
|
||||||
|
nwords--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: sam_cancel
|
* Name: sam_cancel
|
||||||
*
|
*
|
||||||
@@ -2703,6 +2890,7 @@ static bool sam_dmasupported(FAR struct sdio_dev_s *dev)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef HSCMI_NORXDMA
|
||||||
static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||||
size_t buflen)
|
size_t buflen)
|
||||||
{
|
{
|
||||||
@@ -2729,7 +2917,7 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
DEBUGASSERT(nblocks > 0 && blocksize > 0 && (blocksize & 3) == 0);
|
DEBUGASSERT(nblocks > 0 && blocksize > 0 && (blocksize & 3) == 0);
|
||||||
|
|
||||||
/* Physical address of the HSCMI source register, either the TDR (for
|
/* Physical address of the HSCMI source register, either the TDR (for
|
||||||
* single transfers) or the first FIFO register, and the physcal address
|
* single transfers) or the first FIFO register, and the physical address
|
||||||
* of the buffer in RAM.
|
* of the buffer in RAM.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2777,6 +2965,7 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
sam_configxfrints(priv, HSMCI_DMARECV_INTS);
|
sam_configxfrints(priv, HSMCI_DMARECV_INTS);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: sam_dmasendsetup
|
* Name: sam_dmasendsetup
|
||||||
@@ -2797,10 +2986,10 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef HSCMI_NOTXDMA
|
||||||
static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
|
static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
|
||||||
FAR const uint8_t *buffer, size_t buflen)
|
FAR const uint8_t *buffer, size_t buflen)
|
||||||
{
|
{
|
||||||
#ifndef HSCMI_NOTXDMA
|
|
||||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
||||||
uint32_t paddr;
|
uint32_t paddr;
|
||||||
uint32_t maddr;
|
uint32_t maddr;
|
||||||
@@ -2823,7 +3012,7 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
|
|||||||
DEBUGASSERT(nblocks > 0 && blocksize > 0 && (blocksize & 3) == 0);
|
DEBUGASSERT(nblocks > 0 && blocksize > 0 && (blocksize & 3) == 0);
|
||||||
|
|
||||||
/* Physical address of the HSCMI source register, either the TDR (for
|
/* Physical address of the HSCMI source register, either the TDR (for
|
||||||
* single transfers) or the first FIFO register, and the physcal address
|
* single transfers) or the first FIFO register, and the physical address
|
||||||
* of the buffer in RAM.
|
* of the buffer in RAM.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2869,62 +3058,9 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev,
|
|||||||
|
|
||||||
sam_xfrsample(priv, SAMPLENDX_AFTER_SETUP);
|
sam_xfrsample(priv, SAMPLENDX_AFTER_SETUP);
|
||||||
sam_configxfrints(priv, HSMCI_DMASEND_INTS);
|
sam_configxfrints(priv, HSMCI_DMASEND_INTS);
|
||||||
|
|
||||||
#else
|
|
||||||
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
|
|
||||||
unsigned int nwords;
|
|
||||||
const uint32_t *ptr;
|
|
||||||
uint32_t sr;
|
|
||||||
|
|
||||||
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
|
|
||||||
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
|
|
||||||
|
|
||||||
/* Disable DMA handshaking */
|
|
||||||
|
|
||||||
sam_putreg(priv, 0, SAM_HSMCI_DMA_OFFSET);
|
|
||||||
sam_configxfrints(priv, HSMCI_DMASEND_INTS);
|
|
||||||
|
|
||||||
priv->dmabusy = false;
|
|
||||||
priv->xfrbusy = true;
|
|
||||||
priv->txbusy = true;
|
|
||||||
|
|
||||||
/* Nullify register sampling */
|
|
||||||
|
|
||||||
sam_xfrsampleinit(priv);
|
|
||||||
|
|
||||||
/* Copy each word to the TX FIFO
|
|
||||||
*
|
|
||||||
* REVISIT: If TX data underruns occur, then it may be necessary to
|
|
||||||
* disable pre-emption around this loop.
|
|
||||||
*/
|
|
||||||
|
|
||||||
nwords = (buflen + 3) >> 2;
|
|
||||||
ptr = (const uint32_t *)buffer;
|
|
||||||
|
|
||||||
while (nwords > 0)
|
|
||||||
{
|
|
||||||
/* Check the HSMCI status */
|
|
||||||
|
|
||||||
sr = sam_getreg(priv, SAM_HSMCI_SR_OFFSET);
|
|
||||||
if ((sr & HSMCI_DATA_DMASEND_ERRORS) != 0)
|
|
||||||
{
|
|
||||||
/* Some fatal error has occurred */
|
|
||||||
|
|
||||||
fdbg("ERROR: sr %08x\n", sr);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
else if ((sr & HSMCI_INT_TXRDY) != 0)
|
|
||||||
{
|
|
||||||
/* TXRDY -- transfer another word */
|
|
||||||
|
|
||||||
sam_putreg(priv, *ptr++, SAM_HSMCI_TDR_OFFSET);
|
|
||||||
nwords--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Initialization/uninitialization/reset
|
* Initialization/uninitialization/reset
|
||||||
|
|||||||
Reference in New Issue
Block a user