Additional Kinetis SDHC fixes
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3906 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
4c5d5b8192
commit
c2aa7d046c
@ -140,24 +140,15 @@
|
|||||||
#define SDHC_TXDMA32_CONFIG (CONFIG_KINETIS_SDHC_DMAPRIO|DMA_CCR_MSIZE_32BITS|\
|
#define SDHC_TXDMA32_CONFIG (CONFIG_KINETIS_SDHC_DMAPRIO|DMA_CCR_MSIZE_32BITS|\
|
||||||
DMA_CCR_PSIZE_32BITS|DMA_CCR_MINC|DMA_CCR_DIR)
|
DMA_CCR_PSIZE_32BITS|DMA_CCR_MINC|DMA_CCR_DIR)
|
||||||
|
|
||||||
/* Data transfer interrupt mask bits */
|
/* Data transfer / Event waiting interrupt mask bits */
|
||||||
|
|
||||||
#define SDHC_RECV_MASK (SDHC_INT_BRR|SDHC_INT_DCE|SDHC_INT_DTOE|\
|
|
||||||
SDHC_INT_DEBE)
|
|
||||||
#define SDHC_SEND_MASK (SDHC_INT_BWR|SDHC_INT_DCE|SDHC_INT_DTOE|\
|
|
||||||
SDHC_INT_DEBE)
|
|
||||||
#define SDHC_DMARECV_MASK (SDHC_INT_DINT|DHC_INT_DCE|SDHC_INT_DTOE|\
|
|
||||||
SDHC_INT_DEBE|SDHC_INT_DMAE)
|
|
||||||
#define SDHC_DMASEND_MASK (SDHC_INT_DINT|SDHC_INT_DCE|SDHC_INT_DTOE|\
|
|
||||||
SDHC_INT_DEBE|SDHC_INT_DMAE)
|
|
||||||
|
|
||||||
/* Event waiting interrupt mask bits */
|
|
||||||
|
|
||||||
#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_XFDERR_INTS (SDHC_INT_DCE|SDHC_INT_DTOE|SDHC_INT_DEBE)
|
#define SCHC_XFRERR_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_RCVDONE_INTS (SCHC_XFRERR_INTS|SDHC_INT_BRR|SDHC_INT_TC)
|
||||||
#define SDHC_DMADONE_INTS (SDHC_XFDERR_INTS|SDHC_INT_DINT)
|
#define SDHC_SNDDONE_INTS (SCHC_XFRERR_INTS|SDHC_INT_BWR|SDHC_INT_TC)
|
||||||
|
#define SDHC_XFRDONE_INTS (SCHC_XFRERR_INTS|SDHC_INT_BRR|SDHC_INT_BWR|SDHC_INT_TC)
|
||||||
|
#define SDHC_DMADONE_INTS (SCHC_XFRERR_INTS|SDHC_INT_DINT)
|
||||||
|
|
||||||
#define SDHC_WAITALL_INTS (SDHC_RESPDONE_INTS|SDHC_XFRDONE_INTS|SDHC_DMADONE_INTS)
|
#define SDHC_WAITALL_INTS (SDHC_RESPDONE_INTS|SDHC_XFRDONE_INTS|SDHC_DMADONE_INTS)
|
||||||
|
|
||||||
@ -308,8 +299,8 @@ static void kinetis_dataconfig(struct kinetis_dev_s *priv, bool bwrite,
|
|||||||
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_transmit(struct kinetis_dev_s *priv);
|
||||||
static void kinetis_recvfifo(struct kinetis_dev_s *priv);
|
static void kinetis_receive(struct kinetis_dev_s *priv);
|
||||||
static void kinetis_eventtimeout(int argc, uint32_t arg);
|
static void kinetis_eventtimeout(int argc, uint32_t arg);
|
||||||
static void kinetis_endwait(struct kinetis_dev_s *priv, sdio_eventset_t wkupevent);
|
static void kinetis_endwait(struct kinetis_dev_s *priv, sdio_eventset_t wkupevent);
|
||||||
static void kinetis_endtransfer(struct kinetis_dev_s *priv, sdio_eventset_t wkupevent);
|
static void kinetis_endtransfer(struct kinetis_dev_s *priv, sdio_eventset_t wkupevent);
|
||||||
@ -842,7 +833,7 @@ static void kinetis_datadisable(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: kinetis_sendfifo
|
* Name: kinetis_transmit
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Send SDIO data in interrupt mode
|
* Send SDIO data in interrupt mode
|
||||||
@ -855,20 +846,23 @@ static void kinetis_datadisable(void)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void kinetis_sendfifo(struct kinetis_dev_s *priv)
|
static void kinetis_transmit(struct kinetis_dev_s *priv)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
uint32_t w;
|
uint32_t w;
|
||||||
uint8_t b[2];
|
uint8_t b[4];
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
/* Loop while there is more data to be sent, waiting for buffer write
|
/* Loop while there is more data to be sent, waiting for buffer write
|
||||||
* ready (BWR)
|
* ready (BWR)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
fllvdbg("Entry: remaining: %d IRQSTAT: %08x\n",
|
||||||
|
priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT));
|
||||||
|
|
||||||
while (priv->remaining > 0 &&
|
while (priv->remaining > 0 &&
|
||||||
(getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_BWR) == 0)
|
(getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_BWR) != 0)
|
||||||
{
|
{
|
||||||
/* Is there a full word remaining in the user buffer? */
|
/* Is there a full word remaining in the user buffer? */
|
||||||
|
|
||||||
@ -881,32 +875,36 @@ static void kinetis_sendfifo(struct kinetis_dev_s *priv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No.. transfer just the bytes remaining in the user buffer,
|
/* No.. transfer just the bytes remaining in the user buffer,
|
||||||
* padding with zero as necessary to extend to a full word.
|
* padding with zero as necessary to extend to a full word.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint8_t *ptr = (uint8_t *)priv->remaining;
|
uint8_t *ptr = (uint8_t *)priv->remaining;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
data.w = 0;
|
data.w = 0;
|
||||||
for (i = 0; i < priv->remaining; i++)
|
for (i = 0; i < priv->remaining; i++)
|
||||||
{
|
{
|
||||||
data.b[i] = *ptr++;
|
data.b[i] = *ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now the transfer is finished */
|
/* Now the transfer is finished */
|
||||||
|
|
||||||
priv->remaining = 0;
|
priv->remaining = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the word in the FIFO */
|
/* Put the word in the FIFO */
|
||||||
|
|
||||||
putreg32(data.w, KINETIS_SDHC_DATPORT);
|
putreg32(data.w, KINETIS_SDHC_DATPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fllvdbg("Exit: remaining: %d IRQSTAT: %08x\n",
|
||||||
|
priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: kinetis_recvfifo
|
* Name: kinetis_receive
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Receive SDIO data in interrupt mode
|
* Receive SDIO data in interrupt mode
|
||||||
@ -919,18 +917,21 @@ static void kinetis_sendfifo(struct kinetis_dev_s *priv)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void kinetis_recvfifo(struct kinetis_dev_s *priv)
|
static void kinetis_receive(struct kinetis_dev_s *priv)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
uint32_t w;
|
uint32_t w;
|
||||||
uint8_t b[2];
|
uint8_t b[4];
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
/* Loop while there is space to store the data, waiting for buffer read
|
/* Loop while there is space to store the data, waiting for buffer read
|
||||||
* ready (BWR)
|
* ready (BRR)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
fllvdbg("Entry: remaining: %d IRQSTAT: %08x\n",
|
||||||
|
priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT));
|
||||||
|
|
||||||
while (priv->remaining > 0 &&
|
while (priv->remaining > 0 &&
|
||||||
(getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_BRR) != 0)
|
(getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_BRR) != 0)
|
||||||
{
|
{
|
||||||
@ -961,6 +962,10 @@ static void kinetis_recvfifo(struct kinetis_dev_s *priv)
|
|||||||
priv->remaining = 0;
|
priv->remaining = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fllvdbg("Exit: remaining: %d IRQSTAT: %08x\n",
|
||||||
|
priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -1132,6 +1137,8 @@ static int kinetis_interrupt(int irq, void *context)
|
|||||||
|
|
||||||
regval = getreg32(KINETIS_SDHC_IRQSIGEN);
|
regval = getreg32(KINETIS_SDHC_IRQSIGEN);
|
||||||
enabled = getreg32(KINETIS_SDHC_IRQSTAT) & regval;
|
enabled = getreg32(KINETIS_SDHC_IRQSTAT) & regval;
|
||||||
|
fllvdbg("IRQSTAT: %08x IRQSIGEN %08x enabled: %08x\n",
|
||||||
|
getreg32(KINETIS_SDHC_IRQSTAT), regval, enabled);
|
||||||
|
|
||||||
/* Disable card interrupts to clear the card interrupt to the host system. */
|
/* Disable card interrupts to clear the card interrupt to the host system. */
|
||||||
|
|
||||||
@ -1156,10 +1163,10 @@ static int kinetis_interrupt(int irq, void *context)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if ((pending & SDHC_INT_BRR) != 0)
|
if ((pending & SDHC_INT_BRR) != 0)
|
||||||
{
|
{
|
||||||
/* Receive data from the RX buffer */
|
/* Receive data from the RX buffer */
|
||||||
|
|
||||||
kinetis_recvfifo(priv);
|
kinetis_receive(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, Is the TX buffer write ready? If so we must
|
/* Otherwise, Is the TX buffer write ready? If so we must
|
||||||
@ -1171,13 +1178,13 @@ static int kinetis_interrupt(int irq, void *context)
|
|||||||
{
|
{
|
||||||
/* Send data via the TX FIFO */
|
/* Send data via the TX FIFO */
|
||||||
|
|
||||||
kinetis_sendfifo(priv);
|
kinetis_transmit(priv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle data end events */
|
/* Handle data end events */
|
||||||
|
|
||||||
if ((pending & SDHC_INT_DEBE) != 0)
|
if ((pending & SDHC_INT_TC) != 0)
|
||||||
{
|
{
|
||||||
/* Handle any data remaining the RX buffer */
|
/* Handle any data remaining the RX buffer */
|
||||||
|
|
||||||
@ -1208,9 +1215,9 @@ static int kinetis_interrupt(int irq, void *context)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* Receive data from the RX FIFO */
|
/* Receive any additional data from the RX FIFO */
|
||||||
|
|
||||||
kinetis_recvfifo(priv);
|
kinetis_receive(priv);
|
||||||
|
|
||||||
/* Then terminate the transfer */
|
/* Then terminate the transfer */
|
||||||
|
|
||||||
@ -1974,7 +1981,7 @@ static int kinetis_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
|
|
||||||
/* And enable interrupts */
|
/* And enable interrupts */
|
||||||
|
|
||||||
kinetis_configxfrints(priv, SDHC_RECV_MASK);
|
kinetis_configxfrints(priv, SDHC_RCVDONE_INTS);
|
||||||
kinetis_sample(priv, SAMPLENDX_AFTER_SETUP);
|
kinetis_sample(priv, SAMPLENDX_AFTER_SETUP);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -2026,7 +2033,7 @@ static int kinetis_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buff
|
|||||||
|
|
||||||
/* Enable TX interrrupts */
|
/* Enable TX interrrupts */
|
||||||
|
|
||||||
kinetis_configxfrints(priv, SDHC_SEND_MASK);
|
kinetis_configxfrints(priv, SDHC_SNDDONE_INTS);
|
||||||
kinetis_sample(priv, SAMPLENDX_AFTER_SETUP);
|
kinetis_sample(priv, SAMPLENDX_AFTER_SETUP);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -2692,7 +2699,7 @@ static int kinetis_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
|
|
||||||
/* Configure the RX DMA */
|
/* Configure the RX DMA */
|
||||||
|
|
||||||
kinetis_configxfrints(priv, SDHC_DMARECV_MASK);
|
kinetis_configxfrints(priv, SDHC_DMADONE_INTS);
|
||||||
|
|
||||||
putreg32(1, SDHC_DCTRL_DMAEN_BB);
|
putreg32(1, SDHC_DCTRL_DMAEN_BB);
|
||||||
kinetis_dmasetup(priv->dma, KINETIS_SDHC_FIFO, (uint32_t)buffer,
|
kinetis_dmasetup(priv->dma, KINETIS_SDHC_FIFO, (uint32_t)buffer,
|
||||||
@ -2775,7 +2782,7 @@ static int kinetis_dmasendsetup(FAR struct sdio_dev_s *dev,
|
|||||||
|
|
||||||
/* Enable TX interrrupts */
|
/* Enable TX interrrupts */
|
||||||
|
|
||||||
kinetis_configxfrints(priv, SDHC_DMASEND_MASK);
|
kinetis_configxfrints(priv, SDHC_DMADONE_INTS);
|
||||||
|
|
||||||
ret = OK;
|
ret = OK;
|
||||||
}
|
}
|
||||||
|
@ -882,7 +882,7 @@ static void stm32_sendfifo(struct stm32_dev_s *priv)
|
|||||||
union
|
union
|
||||||
{
|
{
|
||||||
uint32_t w;
|
uint32_t w;
|
||||||
uint8_t b[2];
|
uint8_t b[4];
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
/* Loop while there is more data to be sent and the RX FIFO is not full */
|
/* Loop while there is more data to be sent and the RX FIFO is not full */
|
||||||
@ -944,7 +944,7 @@ static void stm32_recvfifo(struct stm32_dev_s *priv)
|
|||||||
union
|
union
|
||||||
{
|
{
|
||||||
uint32_t w;
|
uint32_t w;
|
||||||
uint8_t b[2];
|
uint8_t b[4];
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
/* Loop while there is space to store the data and there is more
|
/* Loop while there is space to store the data and there is more
|
||||||
|
@ -76,7 +76,6 @@
|
|||||||
|
|
||||||
/* Timing (all in units of microseconds) */
|
/* Timing (all in units of microseconds) */
|
||||||
|
|
||||||
#define MMCSD_
|
|
||||||
#define MMCSD_POWERUP_DELAY ((useconds_t)250) /* 74 clock cycles @ 400KHz = 185uS */
|
#define MMCSD_POWERUP_DELAY ((useconds_t)250) /* 74 clock cycles @ 400KHz = 185uS */
|
||||||
#define MMCSD_IDLE_DELAY ((useconds_t)50000) /* Short delay to allow change to IDLE state */
|
#define MMCSD_IDLE_DELAY ((useconds_t)50000) /* Short delay to allow change to IDLE state */
|
||||||
#define MMCSD_DSR_DELAY ((useconds_t)100000) /* Time to wait after setting DSR */
|
#define MMCSD_DSR_DELAY ((useconds_t)100000) /* Time to wait after setting DSR */
|
||||||
@ -86,7 +85,7 @@
|
|||||||
*
|
*
|
||||||
* For MMC & SD V1.x, these should be based on Nac = TAAC + NSAC; The maximum
|
* For MMC & SD V1.x, these should be based on Nac = TAAC + NSAC; The maximum
|
||||||
* value of TAAC is 80MS and the maximum value of NSAC is 25.5K clock cycle.
|
* value of TAAC is 80MS and the maximum value of NSAC is 25.5K clock cycle.
|
||||||
* For SD V2.x, a fixed delay of 100MS is recommend which is preety close to
|
* For SD V2.x, a fixed delay of 100MS is recommend which is pretty close to
|
||||||
* the worst case SD V1.x Nac. Here we just use 100MS delay for all data
|
* the worst case SD V1.x Nac. Here we just use 100MS delay for all data
|
||||||
* transfers.
|
* transfers.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user