More Kinetis SDHC fixes
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3908 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
4d1dfb9002
commit
2b263f9031
@ -133,6 +133,10 @@
|
|||||||
#define SDHC_DVS_MAXTIMEOUT (14)
|
#define SDHC_DVS_MAXTIMEOUT (14)
|
||||||
#define SDHC_DVS_DATATIMEOUT (14)
|
#define SDHC_DVS_DATATIMEOUT (14)
|
||||||
|
|
||||||
|
/* Maximum watermark value */
|
||||||
|
|
||||||
|
#define SDHC_MAX_WATERMARK 128
|
||||||
|
|
||||||
/* DMA CCR register settings */
|
/* DMA CCR register settings */
|
||||||
|
|
||||||
#define SDHC_RXDMA32_CONFIG (CONFIG_KINETIS_SDHC_DMAPRIO|DMA_CCR_MSIZE_32BITS|\
|
#define SDHC_RXDMA32_CONFIG (CONFIG_KINETIS_SDHC_DMAPRIO|DMA_CCR_MSIZE_32BITS|\
|
||||||
@ -144,11 +148,14 @@
|
|||||||
|
|
||||||
#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 SCHC_XFRERR_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_RCVDONE_INTS (SCHC_XFRERR_INTS|SDHC_INT_BRR|SDHC_INT_TC)
|
#define SDHC_RCVDONE_INTS (SCHC_XFRERR_INTS|SDHC_INT_BRR|SDHC_INT_TC)
|
||||||
#define SDHC_SNDDONE_INTS (SCHC_XFRERR_INTS|SDHC_INT_BWR|SDHC_INT_TC)
|
#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_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 SCHC_DMAERR_INTS (SDHC_INT_DCE|SDHC_INT_DTOE|SDHC_INT_DEBE|SDHC_INT_DMAE)
|
||||||
|
#define SDHC_DMADONE_INTS (SCHC_DMAERR_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)
|
||||||
|
|
||||||
@ -211,7 +218,6 @@ struct kinetis_dev_s
|
|||||||
|
|
||||||
/* DMA data transfer support */
|
/* DMA data transfer support */
|
||||||
|
|
||||||
bool widebus; /* Required for DMA support */
|
|
||||||
#ifdef CONFIG_SDIO_DMA
|
#ifdef CONFIG_SDIO_DMA
|
||||||
volatile uint8_t xfrflags; /* Used to synchronize SDIO and DMA completion events */
|
volatile uint8_t xfrflags; /* Used to synchronize SDIO and DMA completion events */
|
||||||
bool dmamode; /* true: DMA mode transfer */
|
bool dmamode; /* true: DMA mode transfer */
|
||||||
@ -791,18 +797,25 @@ static void kinetis_dataconfig(struct kinetis_dev_s *priv, bool bwrite,
|
|||||||
if (bwrite)
|
if (bwrite)
|
||||||
{
|
{
|
||||||
/* Write Watermark Level = 0: BWR will be set when the number of
|
/* Write Watermark Level = 0: BWR will be set when the number of
|
||||||
* queued bytes is less than or equal to 0.
|
* queued words is less than or equal to 0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
putreg32(0, KINETIS_SDHC_WML);
|
putreg32(0, KINETIS_SDHC_WML);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Read Watermark Level = 1: BRR will be set when the number of
|
/* Set the Read Watermark Level to the blocksize to be read
|
||||||
* queued bytes is greater than or equal to 1.
|
* (limited to half of the maximum watermark value). BRR will be
|
||||||
|
* set when the number of queued words is greater than or equal
|
||||||
|
* to this value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
putreg32(1 << SDHC_WML_RD_SHIFT, KINETIS_SDHC_WML);
|
unsigned int watermark = (blocksize + 3) >> 2;
|
||||||
|
if (watermark > (SDHC_MAX_WATERMARK / 2))
|
||||||
|
{
|
||||||
|
watermark = (SDHC_MAX_WATERMARK / 2);
|
||||||
|
}
|
||||||
|
putreg32(watermark << SDHC_WML_RD_SHIFT, KINETIS_SDHC_WML);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -864,6 +877,12 @@ static void kinetis_transmit(struct kinetis_dev_s *priv)
|
|||||||
while (priv->remaining > 0 &&
|
while (priv->remaining > 0 &&
|
||||||
(getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_BWR) != 0)
|
(getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_BWR) != 0)
|
||||||
{
|
{
|
||||||
|
/* Clear BWR. If there is more data in the buffer, writing to the
|
||||||
|
* buffer should reset BRR.
|
||||||
|
*/
|
||||||
|
|
||||||
|
putreg32(SDHC_INT_BWR, KINETIS_SDHC_IRQSTAT);
|
||||||
|
|
||||||
/* Is there a full word remaining in the user buffer? */
|
/* Is there a full word remaining in the user buffer? */
|
||||||
|
|
||||||
if (priv->remaining >= sizeof(uint32_t))
|
if (priv->remaining >= sizeof(uint32_t))
|
||||||
@ -919,12 +938,19 @@ static void kinetis_transmit(struct kinetis_dev_s *priv)
|
|||||||
|
|
||||||
static void kinetis_receive(struct kinetis_dev_s *priv)
|
static void kinetis_receive(struct kinetis_dev_s *priv)
|
||||||
{
|
{
|
||||||
|
unsigned int watermark;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
uint32_t w;
|
uint32_t w;
|
||||||
uint8_t b[4];
|
uint8_t b[4];
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
|
/* Set the Read Watermark Level to 1: BRR will be set when the number of
|
||||||
|
* queued words is greater than or equal to 1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
putreg32(1 << SDHC_WML_RD_SHIFT, KINETIS_SDHC_WML);
|
||||||
|
|
||||||
/* 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 (BRR)
|
* ready (BRR)
|
||||||
*/
|
*/
|
||||||
@ -935,7 +961,13 @@ static void kinetis_receive(struct kinetis_dev_s *priv)
|
|||||||
while (priv->remaining > 0 &&
|
while (priv->remaining > 0 &&
|
||||||
(getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_BRR) != 0)
|
(getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_BRR) != 0)
|
||||||
{
|
{
|
||||||
/* Read the next word from the RX FIFO */
|
/* Clear BRR. If there is more data in the buffer, reading from the
|
||||||
|
* buffer should reset BRR.
|
||||||
|
*/
|
||||||
|
|
||||||
|
putreg32(SDHC_INT_BRR, KINETIS_SDHC_IRQSTAT);
|
||||||
|
|
||||||
|
/* Read the next word from the RX buffer */
|
||||||
|
|
||||||
data.w = getreg32(KINETIS_SDHC_DATPORT);
|
data.w = getreg32(KINETIS_SDHC_DATPORT);
|
||||||
if (priv->remaining >= sizeof(uint32_t))
|
if (priv->remaining >= sizeof(uint32_t))
|
||||||
@ -963,8 +995,20 @@ static void kinetis_receive(struct kinetis_dev_s *priv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fllvdbg("Exit: remaining: %d IRQSTAT: %08x\n",
|
/* Set the Read Watermark Level either the number of remaining words to be
|
||||||
priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT));
|
* read (limited to half of the maximum watermark value)
|
||||||
|
*/
|
||||||
|
|
||||||
|
watermark = ((priv->remaining + 3) >> 2);
|
||||||
|
if (watermark > (SDHC_MAX_WATERMARK / 2))
|
||||||
|
{
|
||||||
|
watermark = (SDHC_MAX_WATERMARK / 2);
|
||||||
|
}
|
||||||
|
putreg32(watermark << SDHC_WML_RD_SHIFT, KINETIS_SDHC_WML);
|
||||||
|
|
||||||
|
fllvdbg("Exit: remaining: %d IRQSTAT: %08x WML: %08x\n",
|
||||||
|
priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT),
|
||||||
|
getreg32(KINETIS_SDHC_WML));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1384,7 +1428,6 @@ static void kinetis_reset(FAR struct sdio_dev_s *dev)
|
|||||||
|
|
||||||
/* DMA data transfer support */
|
/* DMA data transfer support */
|
||||||
|
|
||||||
priv->widebus = false; /* Required for DMA support */
|
|
||||||
#ifdef CONFIG_SDIO_DMA
|
#ifdef CONFIG_SDIO_DMA
|
||||||
priv->dmamode = false; /* true: DMA mode transfer */
|
priv->dmamode = false; /* true: DMA mode transfer */
|
||||||
#endif
|
#endif
|
||||||
@ -1429,8 +1472,21 @@ static uint8_t kinetis_status(FAR struct sdio_dev_s *dev)
|
|||||||
|
|
||||||
static void kinetis_widebus(FAR struct sdio_dev_s *dev, bool wide)
|
static void kinetis_widebus(FAR struct sdio_dev_s *dev, bool wide)
|
||||||
{
|
{
|
||||||
struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev;
|
uint32_t regval;
|
||||||
priv->widebus = wide;
|
|
||||||
|
/* Set the Data Transfer Width (DTW) field in the PROCTL register */
|
||||||
|
|
||||||
|
regval = getreg32(KINETIS_SDHC_PROCTL);
|
||||||
|
regval &= ~SDHC_PROCTL_DTW_MASK;
|
||||||
|
if (wide)
|
||||||
|
{
|
||||||
|
regval |= SDHC_PROCTL_DTW_4BIT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
regval |= SDHC_PROCTL_DTW_1BIT;
|
||||||
|
}
|
||||||
|
putreg32(regval, KINETIS_SDHC_PROCTL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -1794,15 +1850,6 @@ static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t ar
|
|||||||
|
|
||||||
if ((cmd & MMCSD_DATAXFR) != 0)
|
if ((cmd & MMCSD_DATAXFR) != 0)
|
||||||
{
|
{
|
||||||
/* CCEN=1: The SDHC will check the CRC field in the response. If an
|
|
||||||
* error is detected, it is reported as a Command CRC Error.
|
|
||||||
*
|
|
||||||
* This probably should not always be set?
|
|
||||||
*/
|
|
||||||
|
|
||||||
#warning "Revisit"
|
|
||||||
regval |= SDHC_XFERTYP_CCCEN;
|
|
||||||
|
|
||||||
/* Yes.. Configure the data transfer */
|
/* Yes.. Configure the data transfer */
|
||||||
|
|
||||||
switch (cmd & MMCSD_DATAXFR_MASK)
|
switch (cmd & MMCSD_DATAXFR_MASK)
|
||||||
@ -1860,24 +1907,24 @@ static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t ar
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MMCSD_R1B_RESPONSE: /* Response length 48, check busy & cmdindex*/
|
case MMCSD_R1B_RESPONSE: /* Response length 48, check busy & cmdindex*/
|
||||||
regval |= (SDHC_XFERTYP_RSPTYP_LEN48BSY | SDHC_XFERTYP_CICEN);
|
regval |= (SDHC_XFERTYP_RSPTYP_LEN48BSY|SDHC_XFERTYP_CICEN|SDHC_XFERTYP_CCCEN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MMCSD_R1_RESPONSE: /* Response length 48, check cmdindex */
|
case MMCSD_R1_RESPONSE: /* Response length 48, check cmdindex */
|
||||||
|
case MMCSD_R5_RESPONSE:
|
||||||
case MMCSD_R6_RESPONSE:
|
case MMCSD_R6_RESPONSE:
|
||||||
regval |= (SDHC_XFERTYP_RSPTYP_LEN48 | SDHC_XFERTYP_CICEN);
|
regval |= (SDHC_XFERTYP_RSPTYP_LEN48|SDHC_XFERTYP_CICEN|SDHC_XFERTYP_CCCEN);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMCSD_R2_RESPONSE: /* Response length 136, check CRC */
|
||||||
|
regval |= (SDHC_XFERTYP_RSPTYP_LEN136|SDHC_XFERTYP_CCCEN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MMCSD_R3_RESPONSE: /* Response length 48 */
|
case MMCSD_R3_RESPONSE: /* Response length 48 */
|
||||||
case MMCSD_R4_RESPONSE:
|
case MMCSD_R4_RESPONSE:
|
||||||
case MMCSD_R5_RESPONSE:
|
|
||||||
case MMCSD_R7_RESPONSE:
|
case MMCSD_R7_RESPONSE:
|
||||||
regval |= SDHC_XFERTYP_RSPTYP_LEN48;
|
regval |= SDHC_XFERTYP_RSPTYP_LEN48;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MMCSD_R2_RESPONSE: /* Response length 136 */
|
|
||||||
regval |= SDHC_XFERTYP_RSPTYP_LEN136;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable DMA */
|
/* Enable DMA */
|
||||||
@ -2372,8 +2419,6 @@ static int kinetis_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
|
|||||||
|
|
||||||
static int kinetis_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rnotimpl)
|
static int kinetis_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rnotimpl)
|
||||||
{
|
{
|
||||||
uint32_t regval;
|
|
||||||
|
|
||||||
/* Just return an error */
|
/* Just return an error */
|
||||||
|
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
@ -2652,7 +2697,6 @@ static int kinetis_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
{
|
{
|
||||||
struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev;
|
struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev;
|
||||||
uint32_t blocksize;
|
uint32_t blocksize;
|
||||||
int ret = -EINVAL;
|
|
||||||
|
|
||||||
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
|
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
|
||||||
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
|
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
|
||||||
@ -2661,10 +2705,8 @@ static int kinetis_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
|
|
||||||
kinetis_datadisable();
|
kinetis_datadisable();
|
||||||
|
|
||||||
/* Wide bus operation is required for DMA */
|
/* Begin sampling register values */
|
||||||
|
|
||||||
if (priv->widebus)
|
|
||||||
{
|
|
||||||
kinetis_sampleinit();
|
kinetis_sampleinit();
|
||||||
kinetis_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
kinetis_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
||||||
|
|
||||||
@ -2691,9 +2733,7 @@ static int kinetis_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
kinetis_sample(priv, SAMPLENDX_BEFORE_ENABLE);
|
kinetis_sample(priv, SAMPLENDX_BEFORE_ENABLE);
|
||||||
kinetis_dmastart(priv->dma, kinetis_dmacallback, priv, false);
|
kinetis_dmastart(priv->dma, kinetis_dmacallback, priv, false);
|
||||||
kinetis_sample(priv, SAMPLENDX_AFTER_SETUP);
|
kinetis_sample(priv, SAMPLENDX_AFTER_SETUP);
|
||||||
ret = OK;
|
return OK;
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2722,7 +2762,6 @@ static int kinetis_dmasendsetup(FAR struct sdio_dev_s *dev,
|
|||||||
{
|
{
|
||||||
struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev;
|
struct kinetis_dev_s *priv = (struct kinetis_dev_s *)dev;
|
||||||
uint32_t blocksize;
|
uint32_t blocksize;
|
||||||
int ret = -EINVAL;
|
|
||||||
|
|
||||||
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
|
DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
|
||||||
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
|
DEBUGASSERT(((uint32_t)buffer & 3) == 0);
|
||||||
@ -2731,10 +2770,8 @@ static int kinetis_dmasendsetup(FAR struct sdio_dev_s *dev,
|
|||||||
|
|
||||||
kinetis_datadisable();
|
kinetis_datadisable();
|
||||||
|
|
||||||
/* Wide bus operation is required for DMA */
|
/* Begin sampling register values */
|
||||||
|
|
||||||
if (priv->widebus)
|
|
||||||
{
|
|
||||||
kinetis_sampleinit();
|
kinetis_sampleinit();
|
||||||
kinetis_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
kinetis_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
||||||
|
|
||||||
@ -2764,10 +2801,7 @@ static int kinetis_dmasendsetup(FAR struct sdio_dev_s *dev,
|
|||||||
/* Enable TX interrrupts */
|
/* Enable TX interrrupts */
|
||||||
|
|
||||||
kinetis_configxfrints(priv, SDHC_DMADONE_INTS);
|
kinetis_configxfrints(priv, SDHC_DMADONE_INTS);
|
||||||
|
return OK;
|
||||||
ret = OK;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -331,6 +331,10 @@
|
|||||||
|
|
||||||
#define SDHC_ADMAES_SHIFT (0) /* Bits 0-1: ADMA Error State (when ADMA Error is occurred) */
|
#define SDHC_ADMAES_SHIFT (0) /* Bits 0-1: ADMA Error State (when ADMA Error is occurred) */
|
||||||
#define SDHC_ADMAES_MASK (3 << SDHC_ADMAES_ADMAES_SHIFT)
|
#define SDHC_ADMAES_MASK (3 << SDHC_ADMAES_ADMAES_SHIFT)
|
||||||
|
# define SDHC_ADMAES_STOP (0 << SDHC_ADMAES_ADMAES_SHIFT) /* Stop DMA */
|
||||||
|
# define SDHC_ADMAES_FDS (1 << SDHC_ADMAES_ADMAES_SHIFT) /* Fetch descriptor */
|
||||||
|
# define SDHC_ADMAES_CADR (2 << SDHC_ADMAES_ADMAES_SHIFT) /* Change address */
|
||||||
|
# define SDHC_ADMAES_TFR (3 << SDHC_ADMAES_ADMAES_SHIFT) /* Transfer data */
|
||||||
#define SDHC_ADMAES_LME (1 << 2) /* Bit 2: ADMA Length Mismatch Error */
|
#define SDHC_ADMAES_LME (1 << 2) /* Bit 2: ADMA Length Mismatch Error */
|
||||||
#define SDHC_ADMAES_DCE (1 << 3) /* Bit 3: ADMA Descriptor Error */
|
#define SDHC_ADMAES_DCE (1 << 3) /* Bit 3: ADMA Descriptor Error */
|
||||||
/* Bits 4-31: Reserved */
|
/* Bits 4-31: Reserved */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user