In progress updates to the Kinetis SDHC driver

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3905 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2011-08-22 18:17:42 +00:00
parent a40add6150
commit 4c5d5b8192
2 changed files with 60 additions and 57 deletions

View File

@ -427,9 +427,9 @@ void kinetis_uartconfigure(uintptr_t uart_base, uint32_t baud,
/* Otherwise, disable the FIFOs. Then the FIFOs are disable, the effective /* Otherwise, disable the FIFOs. Then the FIFOs are disable, the effective
* FIFO depth is 1. So set the watermarks as follows: * FIFO depth is 1. So set the watermarks as follows:
* *
* TWFIFO[TXWATER] = 0: TDRE will be set when the number of queues bytes * TWFIFO[TXWATER] = 0: TDRE will be set when the number of queued bytes
* (1 in this case) is less than or equal to 0. * (1 in this case) is less than or equal to 0.
* RWFIFO[RXWATER] = 1: RDRF will be set when the number of queues bytes * RWFIFO[RXWATER] = 1: RDRF will be set when the number of queued bytes
* (1 in this case) is greater than or equal to 1. * (1 in this case) is greater than or equal to 1.
* *
* Set the watermarks to one/zero and disable the FIFOs * Set the watermarks to one/zero and disable the FIFOs

View File

@ -155,9 +155,11 @@
#define SDHC_RESPERR_INTS (SDHC_INT_CCE|SDHC_INT_CTOE|SDHC_INT_CEBE|SDHC_INT_CIE) #define SDHC_RESPERR_INTS (SDHC_INT_CCE|SDHC_INT_CTOE|SDHC_INT_CEBE|SDHC_INT_CIE)
#define SDHC_RESPDONE_INTS (SDHC_RESPERR_INTS|SDHC_INT_CC) #define SDHC_RESPDONE_INTS (SDHC_RESPERR_INTS|SDHC_INT_CC)
#define SDHC_XFDONE_INTS (SDHC_INT_DCE|SDHC_INT_DTOE|SDHC_INT_DEBE) #define SDHC_XFDERR_INTS (SDHC_INT_DCE|SDHC_INT_DTOE|SDHC_INT_DEBE)
#define SDHC_XFRDONE_INTS (SDHC_XFDERR_INTS|SDHC_INT_BRR|SDHC_INT_BWR)
#define SDHC_DMADONE_INTS (SDHC_XFDERR_INTS|SDHC_INT_DINT)
#define SDHC_WAITALL_INTS (SDHC_RESPDONE_INTS|SDHC_XFDONE_INTS) #define SDHC_WAITALL_INTS (SDHC_RESPDONE_INTS|SDHC_XFRDONE_INTS|SDHC_DMADONE_INTS)
/* Let's wait until we have both SDIO transfer complete and DMA complete. */ /* Let's wait until we have both SDIO transfer complete and DMA complete. */
@ -302,8 +304,8 @@ static void kinetis_dmacallback(DMA_HANDLE handle, uint8_t isr, void *arg);
/* Data Transfer Helpers ****************************************************/ /* Data Transfer Helpers ****************************************************/
static uint8_t kinetis_log2(uint16_t value); static void kinetis_dataconfig(struct kinetis_dev_s *priv, bool bwrite,
static void kinetis_dataconfig(unsigned int blocksize, unsigned int nblocks, unsigned int blocksize, unsigned int nblocks,
unsigned int timeout); unsigned int timeout);
static void kinetis_datadisable(void); static void kinetis_datadisable(void);
static void kinetis_sendfifo(struct kinetis_dev_s *priv); static void kinetis_sendfifo(struct kinetis_dev_s *priv);
@ -752,36 +754,6 @@ static void kinetis_dmacallback(DMA_HANDLE handle, uint8_t isr, void *arg)
* Data Transfer Helpers * Data Transfer Helpers
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: kinetis_log2
*
* Description:
* Take (approximate) log base 2 of the provided number (Only works if the
* provided number is a power of 2).
*
****************************************************************************/
static uint8_t kinetis_log2(uint16_t value)
{
uint8_t log2 = 0;
/* 0000 0000 0000 0001 -> return 0,
* 0000 0000 0000 001x -> return 1,
* 0000 0000 0000 01xx -> return 2,
* 0000 0000 0000 1xxx -> return 3,
* ...
* 1xxx xxxx xxxx xxxx -> return 15,
*/
DEBUGASSERT(value > 0);
while (value != 1)
{
value >>= 1;
log2++;
}
return log2;
}
/**************************************************************************** /****************************************************************************
* Name: kinetis_dataconfig * Name: kinetis_dataconfig
* *
@ -790,7 +762,8 @@ static uint8_t kinetis_log2(uint16_t value)
* *
****************************************************************************/ ****************************************************************************/
static void kinetis_dataconfig(unsigned int blocksize, unsigned int nblocks, static void kinetis_dataconfig(struct kinetis_dev_s *priv, bool bwrite,
unsigned int blocksize, unsigned int nblocks,
unsigned int timeout) unsigned int timeout)
{ {
uint32_t regval = 0; uint32_t regval = 0;
@ -809,6 +782,38 @@ static void kinetis_dataconfig(unsigned int blocksize, unsigned int nblocks,
regval = blocksize << SDHC_BLKATTR_SIZE_SHIFT | regval = blocksize << SDHC_BLKATTR_SIZE_SHIFT |
nblocks << SDHC_BLKATTR_CNT_SHIFT; nblocks << SDHC_BLKATTR_CNT_SHIFT;
putreg32(regval, KINETIS_SDHC_BLKATTR); putreg32(regval, KINETIS_SDHC_BLKATTR);
/* Set the watermark level */
#ifdef CONFIG_SDIO_DMA
if (priv->dma)
{
# warning "Missing logic"
}
else
#endif
{
/* For now, treat the FIFO as though it had depth = 1. Set the
* read/write watermarks as follows:
*/
if (bwrite)
{
/* Write Watermark Level = 0: BWR will be set when the number of
* queued bytes is less than or equal to 0.
*/
putreg32(0, KINETIS_SDHC_WML);
}
else
{
/* Read Watermark Level = 1: BRR will be set when the number of
* queued bytes is greater than or equal to 1.
*/
putreg32(1 << SDHC_WML_RD_SHIFT, KINETIS_SDHC_WML);
}
}
} }
/**************************************************************************** /****************************************************************************
@ -988,7 +993,11 @@ static void kinetis_eventtimeout(int argc, uint32_t arg)
if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0) if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
{ {
/* Yes.. wake up any waiting threads */ /* Yes.. Sample registers at the time of the timeout */
kinetis_sample(priv, SAMPLENDX_END_TRANSFER);
/* Wake up any waiting threads */
kinetis_endwait(priv, SDIOWAIT_TIMEOUT); kinetis_endwait(priv, SDIOWAIT_TIMEOUT);
flldbg("Timeout: remaining: %d\n", priv->remaining); flldbg("Timeout: remaining: %d\n", priv->remaining);
@ -1056,7 +1065,7 @@ static void kinetis_endtransfer(struct kinetis_dev_s *priv, sdio_eventset_t wkup
/* Clearing pending interrupt status on all transfer related interrupts */ /* Clearing pending interrupt status on all transfer related interrupts */
putreg32(SDHC_XFDONE_INTS, KINETIS_SDHC_IRQSTAT); putreg32(SDHC_XFRDONE_INTS, KINETIS_SDHC_IRQSTAT);
/* If this was a DMA transfer, make sure that DMA is stopped */ /* If this was a DMA transfer, make sure that DMA is stopped */
@ -1799,26 +1808,26 @@ static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t ar
case MMCSD_RDSTREAM : /* Yes.. streaming read data transfer */ case MMCSD_RDSTREAM : /* Yes.. streaming read data transfer */
#warning "Probably some missing setup" #warning "Probably some missing setup"
regval |= SDHC_XFERTYP_DPSEL; regval |= (SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_DTDSEL);
break; break;
case MMCSD_WRSTREAM : /* Yes.. streaming write data transfer */ case MMCSD_WRSTREAM : /* Yes.. streaming write data transfer */
#warning "Probably some missing setup" #warning "Probably some missing setup"
regval |= (SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_DTDSEL);
break;
case MMCSD_RDDATAXFR : /* Yes.. normal read data transfer */
regval |= SDHC_XFERTYP_DPSEL; regval |= SDHC_XFERTYP_DPSEL;
break; break;
case MMCSD_WRDATAXFR : /* Yes.. normal write data transfer */ case MMCSD_RDDATAXFR : /* Yes.. normal read data transfer */
regval |= (SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_DTDSEL); regval |= (SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_DTDSEL);
break; break;
case MMCSD_WRDATAXFR : /* Yes.. normal write data transfer */
regval |= SDHC_XFERTYP_DPSEL;
break;
} }
/* Is it a multi-block transfer? */ /* Is it a multi-block transfer? */
if ((cmd & MMCSD_DATAXFR) != 0) if ((cmd & MMCSD_MULTIBLOCK) != 0)
{ {
/* Yes.. should the transfer be stopped with ACMD12? */ /* Yes.. should the transfer be stopped with ACMD12? */
@ -1941,7 +1950,6 @@ static int kinetis_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
size_t nbytes) size_t nbytes)
{ {
struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev; struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev;
uint32_t blocksize;
DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0); DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0);
DEBUGASSERT(((uint32_t)buffer & 3) == 0); DEBUGASSERT(((uint32_t)buffer & 3) == 0);
@ -1962,8 +1970,7 @@ static int kinetis_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
/* Then set up the SDIO data path */ /* Then set up the SDIO data path */
blocksize = kinetis_log2(nbytes); kinetis_dataconfig(priv, false, nbytes, 1, SDHC_DVS_DATATIMEOUT);
kinetis_dataconfig(blocksize, 1, SDHC_DVS_DATATIMEOUT);
/* And enable interrupts */ /* And enable interrupts */
@ -1995,7 +2002,6 @@ static int kinetis_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buff
size_t nbytes) size_t nbytes)
{ {
struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev; struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev;
uint32_t blocksize;
DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0); DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0);
DEBUGASSERT(((uint32_t)buffer & 3) == 0); DEBUGASSERT(((uint32_t)buffer & 3) == 0);
@ -2016,8 +2022,7 @@ static int kinetis_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buff
/* Then set up the SDIO data path */ /* Then set up the SDIO data path */
blocksize = kinetis_log2(nbytes); kinetis_dataconfig(priv, true, nbytes, 1, SDHC_DVS_DATATIMEOUT);
kinetis_dataconfig(blocksize, 1, SDHC_DVS_DATATIMEOUT);
/* Enable TX interrrupts */ /* Enable TX interrrupts */
@ -2430,7 +2435,7 @@ static void kinetis_waitenable(FAR struct sdio_dev_s *dev,
if ((eventset & SDIOWAIT_TRANSFERDONE) != 0) if ((eventset & SDIOWAIT_TRANSFERDONE) != 0)
{ {
// waitints |= 0; waitints |= SDHC_XFRDONE_INTS;
} }
/* Enable event-related interrupts */ /* Enable event-related interrupts */
@ -2683,8 +2688,7 @@ static int kinetis_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
/* Then set up the SDIO data path */ /* Then set up the SDIO data path */
blocksize = kinetis_log2(buflen); kinetis_dataconfig(priv, false, buflen, 1, SDHC_DVS_DATATIMEOUT);
kinetis_dataconfig(blocksize, 1, SDHC_DVS_DATATIMEOUT);
/* Configure the RX DMA */ /* Configure the RX DMA */
@ -2754,8 +2758,7 @@ static int kinetis_dmasendsetup(FAR struct sdio_dev_s *dev,
/* Then set up the SDIO data path */ /* Then set up the SDIO data path */
blocksize = kinetis_log2(buflen); kinetis_dataconfig(priv, true, buflen, 1, SDHC_DVS_DATATIMEOUT);
kinetis_dataconfig(blocksize, 1, SDHC_DVS_DATATIMEOUT);
/* Configure the TX DMA */ /* Configure the TX DMA */