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:
parent
a40add6150
commit
4c5d5b8192
@ -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
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user