SAM3U needs block info
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2584 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
da47b386c6
commit
1bee4a3f0f
@ -81,6 +81,10 @@
|
||||
# error "Callback support requires CONFIG_SCHED_WORKQUEUE"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SDIO_BLOCKSETUP
|
||||
# error "This driver requires CONFIG_SDIO_BLOCKSETUP"
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_HSMCI_PRI
|
||||
# define CONFIG_HSMCI_PRI NVIC_SYSH_PRIORITY_DEFAULT
|
||||
#endif
|
||||
@ -89,6 +93,20 @@
|
||||
# undef CONFIG_HSMCI_XFRDEBUG
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAM3U_HSMCI_RDPROOF
|
||||
# ifdef CONFIG_SAM3U_HSMCI_WRPROOF
|
||||
# define HSMCU_PROOF_BITS (HSMCI_MR_RDPROOF | HSMCI_MR_WRPROOF)
|
||||
# else
|
||||
# define HSMCU_PROOF_BITS HSMCI_MR_RDPROOF
|
||||
# endif
|
||||
#else
|
||||
# ifdef CONFIG_SAM3U_HSMCI_WRPROOF
|
||||
# define HSMCU_PROOF_BITS HSMCI_MR_WRPROOF
|
||||
# else
|
||||
# define HSMCU_PROOF_BITS (0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Timing */
|
||||
|
||||
#define HSMCI_CMDTIMEOUT (100000)
|
||||
@ -344,8 +362,9 @@ static int sam3u_attach(FAR struct sdio_dev_s *dev);
|
||||
|
||||
static void sam3u_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
uint32_t arg);
|
||||
static void sam3u_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
|
||||
unsigned int nblocks);
|
||||
static int sam3u_cancel(FAR struct sdio_dev_s *dev);
|
||||
|
||||
static int sam3u_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd);
|
||||
static int sam3u_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
uint32_t *rshort);
|
||||
@ -393,6 +412,7 @@ struct sam3u_dev_s g_sdiodev =
|
||||
.clock = sam3u_clock,
|
||||
.attach = sam3u_attach,
|
||||
.sendcmd = sam3u_sendcmd,
|
||||
.blocksetup = sam3u_blocksetup,
|
||||
.recvsetup = sam3u_dmarecvsetup,
|
||||
.sendsetup = sam3u_dmasendsetup,
|
||||
.cancel = sam3u_cancel,
|
||||
@ -1334,12 +1354,12 @@ static void sam3u_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg
|
||||
case MMCSD_R5_RESPONSE:
|
||||
case MMCSD_R6_RESPONSE:
|
||||
priv->cmdrmask = HSMCI_CMDRESP_INTS;
|
||||
regval |= HSMCI_CMDR_RSPTYP_48BIT;
|
||||
regval |= (HSMCI_CMDR_RSPTYP_48BIT | HSMCI_CMDR_MAXLAT);
|
||||
break;
|
||||
|
||||
case MMCSD_R1B_RESPONSE:
|
||||
priv->cmdrmask = HSMCI_CMDRESP_INTS;
|
||||
regval |= HSMCI_CMDR_RSPTYP_R1B;
|
||||
regval |= (HSMCI_CMDR_RSPTYP_R1B | HSMCI_CMDR_MAXLAT);
|
||||
break;
|
||||
|
||||
/* 48-bit response without CRC */
|
||||
@ -1347,14 +1367,14 @@ static void sam3u_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg
|
||||
case MMCSD_R3_RESPONSE:
|
||||
case MMCSD_R7_RESPONSE:
|
||||
priv->cmdrmask = HSMCI_CMDRESP_NOCRC_INTS;
|
||||
regval |= HSMCI_CMDR_RSPTYP_48BIT;
|
||||
regval |= (HSMCI_CMDR_RSPTYP_48BIT | HSMCI_CMDR_MAXLAT);
|
||||
break;
|
||||
|
||||
/* 136-bit response with CRC */
|
||||
|
||||
case MMCSD_R2_RESPONSE:
|
||||
priv->cmdrmask = HSMCI_CMDRESP_INTS;
|
||||
regval |= HSMCI_CMDR_RSPTYP_136BIT;
|
||||
regval |= (HSMCI_CMDR_RSPTYP_136BIT | HSMCI_CMDR_MAXLAT);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1400,19 +1420,50 @@ static void sam3u_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Special case a couple of commands */
|
||||
|
||||
if (cmdidx > MMC_CMDIDX3 && cmdidx != MMCSD_CMDIDX15 && cmd != MMCSD_CMDIDX27)
|
||||
{
|
||||
regval |= HSMCI_CMDR_MAXLAT; /* Max Latency for Command to Response */
|
||||
}
|
||||
|
||||
/* Write the fully decorated command to CMDR */
|
||||
|
||||
fvdbg("cmd: %08x arg: %08x regval: %08x\n", cmd, arg, regval);
|
||||
putreg32(regval, SAM3U_HSMCI_CMDR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam3u_blocksetup
|
||||
*
|
||||
* Description:
|
||||
* Some hardward needs to be informed of the selected blocksize.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the SDIO device interface
|
||||
* blocklen - The selected block size.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void sam3u_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
|
||||
unsigned int nblocks)
|
||||
{
|
||||
uint32_t regval;
|
||||
|
||||
DEBUGASSERT(dev != NULL && nblocks > 0 && nblocks < 65535 && blocklen < 65535);
|
||||
|
||||
/* Set the block size */
|
||||
|
||||
regval = getreg32(SAM3U_HSMCI_MR);
|
||||
regval &= ~(HSMCI_MR_RDPROOF | HSMCI_MR_WRPROOF | HSMCI_MR_BLKLEN_MASK);
|
||||
regval |= HSMCU_PROOF_BITS;
|
||||
regval |= (blocklen << HSMCI_MR_BLKLEN_SHIFT);
|
||||
putreg32(regval, SAM3U_HSMCI_MR);
|
||||
|
||||
/* Set the block count */
|
||||
|
||||
regval = getreg32(SAM3U_HSMCI_BLKR);
|
||||
regval &= ~HSMCI_BLKR_BCNT_MASK;
|
||||
regval |= (nblocks << HSMCI_BLKR_BCNT_SHIFT);
|
||||
putreg32(regval, SAM3U_HSMCI_BLKR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sam3u_cancel
|
||||
*
|
||||
@ -1988,39 +2039,26 @@ static int sam3u_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
struct sam3u_dev_s *priv = (struct sam3u_dev_s *)dev;
|
||||
int ret = -EINVAL;
|
||||
|
||||
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
|
||||
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
|
||||
|
||||
/* Reset the DPSM configuration */
|
||||
/* Setup register sampling */
|
||||
|
||||
//TO BE PROVIDED
|
||||
sam3u_sampleinit();
|
||||
sam3u_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
||||
|
||||
/* Wide bus operation is required for DMA */
|
||||
/* Configure the RX DMA */
|
||||
|
||||
if (priv->widebus)
|
||||
{
|
||||
sam3u_sampleinit();
|
||||
sam3u_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
||||
|
||||
/* Then set up the HSMCI data path */
|
||||
|
||||
//TO BE PROVIDED
|
||||
|
||||
/* Configure the RX DMA */
|
||||
|
||||
sam3u_enablexfrints(priv, HSMCI_DMARECV_INTS);
|
||||
sam3u_dmarxsetup(priv->dma, SAM3U_HSMCI_FIFO, (uint32_t)buffer, buflen);
|
||||
sam3u_enablexfrints(priv, HSMCI_DMARECV_INTS);
|
||||
sam3u_dmarxsetup(priv->dma, SAM3U_HSMCI_FIFO, (uint32_t)buffer, buflen);
|
||||
|
||||
/* Start the DMA */
|
||||
/* Start the DMA */
|
||||
|
||||
sam3u_sample(priv, SAMPLENDX_BEFORE_ENABLE);
|
||||
sam3u_dmastart(priv->dma, sam3u_dmacallback, priv);
|
||||
sam3u_sample(priv, SAMPLENDX_AFTER_SETUP);
|
||||
ret = OK;
|
||||
}
|
||||
return ret;
|
||||
sam3u_sample(priv, SAMPLENDX_BEFORE_ENABLE);
|
||||
sam3u_dmastart(priv->dma, sam3u_dmacallback, priv);
|
||||
sam3u_sample(priv, SAMPLENDX_AFTER_SETUP);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -2046,43 +2084,29 @@ static int sam3u_dmasendsetup(FAR struct sdio_dev_s *dev,
|
||||
FAR const uint8_t *buffer, size_t buflen)
|
||||
{
|
||||
struct sam3u_dev_s *priv = (struct sam3u_dev_s *)dev;
|
||||
int ret = -EINVAL;
|
||||
|
||||
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
|
||||
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
|
||||
|
||||
/* Reset the DPSM configuration */
|
||||
/* Setup register sampling */
|
||||
|
||||
//TO BE PROVIDED
|
||||
sam3u_sampleinit();
|
||||
sam3u_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
||||
|
||||
/* Wide bus operation is required for DMA */
|
||||
/* Configure the TX DMA */
|
||||
|
||||
if (priv->widebus)
|
||||
{
|
||||
sam3u_sampleinit();
|
||||
sam3u_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
||||
sam3u_dmatxsetup(priv->dma, SAM3U_HSMCI_FIFO, (uint32_t)buffer, buflen);
|
||||
sam3u_sample(priv, SAMPLENDX_BEFORE_ENABLE);
|
||||
|
||||
/* Then set up the HSMCI data path */
|
||||
/* Start the DMA */
|
||||
|
||||
//TO BE PROVIDED
|
||||
sam3u_dmastart(priv->dma, sam3u_dmacallback, priv);
|
||||
sam3u_sample(priv, SAMPLENDX_AFTER_SETUP);
|
||||
|
||||
/* Configure the TX DMA */
|
||||
/* Enable TX interrrupts */
|
||||
|
||||
sam3u_dmatxsetup(priv->dma, SAM3U_HSMCI_FIFO, (uint32_t)buffer, buflen);
|
||||
sam3u_sample(priv, SAMPLENDX_BEFORE_ENABLE);
|
||||
|
||||
/* Start the DMA */
|
||||
|
||||
sam3u_dmastart(priv->dma, sam3u_dmacallback, priv);
|
||||
sam3u_sample(priv, SAMPLENDX_AFTER_SETUP);
|
||||
|
||||
/* Enable TX interrrupts */
|
||||
|
||||
sam3u_enablexfrints(priv, HSMCI_DMASEND_INTS);
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
return ret;
|
||||
sam3u_enablexfrints(priv, HSMCI_DMASEND_INTS);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -461,6 +461,7 @@ static int mmcsd_getSCR(FAR struct mmcsd_state_s *priv, uint32_t scr[2])
|
||||
|
||||
/* Setup up to receive data with interrupt mode */
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, 8, 1);
|
||||
SDIO_RECVSETUP(priv->dev, (FAR uint8_t*)scr, 8);
|
||||
|
||||
/* Send ACMD51 SD_APP_SEND_SCR with argument as 0 to start data receipt */
|
||||
@ -1246,6 +1247,7 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
/* Configure SDIO controller hardware for the read transfer */
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, priv->blocksize, 1);
|
||||
SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR);
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
if (priv->dma)
|
||||
@ -1354,6 +1356,7 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
/* Configure SDIO controller hardware for the read transfer */
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, priv->blocksize, nblocks);
|
||||
SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR);
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
if (priv->dma)
|
||||
@ -1511,6 +1514,7 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
/* Configure SDIO controller hardware for the write transfer */
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, priv->blocksize, 1);
|
||||
SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR);
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
if (priv->dma)
|
||||
@ -1655,6 +1659,7 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
|
||||
|
||||
/* Configure SDIO controller hardware for the write transfer */
|
||||
|
||||
SDIO_BLOCKSETUP(priv->dev, priv->blocksize, nblocks);
|
||||
SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR);
|
||||
#ifdef CONFIG_SDIO_DMA
|
||||
if (priv->dma)
|
||||
|
@ -421,6 +421,29 @@
|
||||
|
||||
#define SDIO_SENDCMD(dev,cmd,arg) ((dev)->sendcmd(dev,cmd,arg))
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_BLOCKLEN
|
||||
*
|
||||
* Description:
|
||||
* Some hardward needs to be informed of the selected blocksize and the
|
||||
* number of blocks. Others just work on the byte stream.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the SDIO device interface
|
||||
* blocklen - The selected block size.
|
||||
* nblocks - The number of blocks to be transferred.
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SDIO_BLOCKSETUP
|
||||
# define SDIO_BLOCKSETUP(dev,blocklen,nblocks) ((dev)->blocksetup(dev,blocklen,nblocks))
|
||||
#else
|
||||
# define SDIO_BLOCKSETUP(dev,blocklen,nblocks)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: SDIO_RECVSETUP
|
||||
*
|
||||
@ -744,6 +767,7 @@ struct sdio_dev_s
|
||||
/* Command/Status/Data Transfer */
|
||||
|
||||
void (*sendcmd)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg);
|
||||
void (*blocksetup)(FAR struct sdio_dev_s *dev, unsigned int blocklen, unsigned int nblocks);
|
||||
int (*recvsetup)(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
size_t nbytes);
|
||||
int (*sendsetup)(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer,
|
||||
|
Loading…
Reference in New Issue
Block a user