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:
patacongo 2010-04-10 23:16:51 +00:00
parent da47b386c6
commit 1bee4a3f0f
3 changed files with 115 additions and 62 deletions

View File

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

View File

@ -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)

View File

@ -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,