Kinetis SDHC driver fixes.

This commit is contained in:
Marc Rechté
2017-02-09 11:28:30 -06:00
committed by Gregory Nutt
parent 248d5d3185
commit d501ffc563
2 changed files with 38 additions and 47 deletions
+34 -45
View File
@@ -116,10 +116,10 @@
# endif # endif
#endif #endif
/* Timing */ /* Timing in ms for commands wait response */
#define SDHC_CMDTIMEOUT (100000) #define SDHC_CMDTIMEOUT MSEC2TICK(100)
#define SDHC_LONGTIMEOUT (0x7fffffff) #define SDHC_LONGTIMEOUT MSEC2TICK(500)
/* Big DTOCV setting. Range is 0=SDCLK*2^13 through 14=SDCLK*2^27 */ /* Big DTOCV setting. Range is 0=SDCLK*2^13 through 14=SDCLK*2^27 */
@@ -675,7 +675,6 @@ static void kinetis_dataconfig(struct kinetis_dev_s *priv, bool bwrite,
/* Set the watermark level */ /* Set the watermark level */
#ifdef CONFIG_KINETIS_SDHC_DMA
/* Set the Read Watermark Level to the blocksize to be read /* Set the Read Watermark Level to the blocksize to be read
* (limited to half of the maximum watermark value). BRR will be * (limited to half of the maximum watermark value). BRR will be
* set when the number of queued words is greater than or equal * set when the number of queued words is greater than or equal
@@ -715,32 +714,6 @@ static void kinetis_dataconfig(struct kinetis_dev_s *priv, bool bwrite,
putreg32(watermark << SDHC_WML_RD_SHIFT, KINETIS_SDHC_WML); putreg32(watermark << SDHC_WML_RD_SHIFT, KINETIS_SDHC_WML);
} }
#else
if (bwrite)
{
/* Write Watermark Level = 0: BWR will be set when the number of
* queued words is less than or equal to 0.
*/
putreg32(0, KINETIS_SDHC_WML);
}
else
{
/* Set the Read Watermark Level to the blocksize to be read
* (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.
*/
watermark = (blocksize + 3) >> 2;
if (watermark > (SDHC_MAX_WATERMARK / 2))
{
watermark = (SDHC_MAX_WATERMARK / 2);
}
putreg32(watermark << SDHC_WML_RD_SHIFT, KINETIS_SDHC_WML);
}
#endif
} }
/**************************************************************************** /****************************************************************************
@@ -791,22 +764,16 @@ static void kinetis_transmit(struct kinetis_dev_s *priv)
uint8_t b[4]; 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, while buffer write enable
* ready (BWR) * (PRSSTAT.BWEN)
*/ */
mcinfo("Entry: remaining: %d IRQSTAT: %08x\n", mcinfo("Entry: remaining: %d IRQSTAT: %08x\n",
priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT)); 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_PRSSTAT) & SDHC_PRSSTAT_BWEN) != 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))
@@ -841,6 +808,12 @@ static void kinetis_transmit(struct kinetis_dev_s *priv)
putreg32(data.w, KINETIS_SDHC_DATPORT); putreg32(data.w, KINETIS_SDHC_DATPORT);
} }
/* Clear BWR. If there is more data in the buffer, writing to the
* buffer should reset BWR.
*/
putreg32(SDHC_INT_BWR, KINETIS_SDHC_IRQSTAT);
mcinfo("Exit: remaining: %d IRQSTAT: %08x\n", mcinfo("Exit: remaining: %d IRQSTAT: %08x\n",
priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT)); priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT));
} }
@@ -1342,6 +1315,7 @@ static sdio_capset_t kinetis_capabilities(FAR struct sdio_dev_s *dev)
#ifdef CONFIG_KINETIS_SDHC_DMA #ifdef CONFIG_KINETIS_SDHC_DMA
caps |= SDIO_CAPS_DMASUPPORTED; caps |= SDIO_CAPS_DMASUPPORTED;
#endif #endif
caps |= SDIO_CAPS_DMABEFOREWRITE;
return caps; return caps;
} }
@@ -1750,11 +1724,14 @@ static int kinetis_attach(FAR struct sdio_dev_s *dev)
* *
****************************************************************************/ ****************************************************************************/
static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg) static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t arg)
{ {
systime_t timeout;
systime_t start;
systime_t elapsed;
uint32_t regval; uint32_t regval;
uint32_t cmdidx; uint32_t cmdidx;
int32_t timeout;
/* Initialize the command index */ /* Initialize the command index */
@@ -1866,9 +1843,14 @@ static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t ar
*/ */
timeout = SDHC_CMDTIMEOUT; timeout = SDHC_CMDTIMEOUT;
start = clock_systimer();
while ((getreg32(KINETIS_SDHC_PRSSTAT) & SDHC_PRSSTAT_CIHB) != 0) while ((getreg32(KINETIS_SDHC_PRSSTAT) & SDHC_PRSSTAT_CIHB) != 0)
{ {
if (--timeout <= 0) /* Calculate the elapsed time */
elapsed = clock_systimer() - start;
if (elapsed >= timeout)
{ {
mcerr("ERROR: Timeout cmd: %08x PRSSTAT: %08x\n", mcerr("ERROR: Timeout cmd: %08x PRSSTAT: %08x\n",
cmd, getreg32(KINETIS_SDHC_PRSSTAT)); cmd, getreg32(KINETIS_SDHC_PRSSTAT));
@@ -2067,9 +2049,11 @@ static int kinetis_cancel(FAR struct sdio_dev_s *dev)
static int kinetis_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd) static int kinetis_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
{ {
systime_t timeout;
systime_t start;
systime_t elapsed;
uint32_t errors; uint32_t errors;
int32_t timeout; int ret = OK;
int ret = OK;
switch (cmd & MMCSD_RESPONSE_MASK) switch (cmd & MMCSD_RESPONSE_MASK)
{ {
@@ -2105,9 +2089,14 @@ static int kinetis_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
* (except Auto CMD12). * (except Auto CMD12).
*/ */
start = clock_systimer();
while ((getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_CC) == 0) while ((getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_CC) == 0)
{ {
if (--timeout <= 0) /* Calculate the elapsed time */
elapsed = clock_systimer() - start;
if (elapsed >= timeout)
{ {
mcerr("ERROR: Timeout cmd: %08x IRQSTAT: %08x\n", mcerr("ERROR: Timeout cmd: %08x IRQSTAT: %08x\n",
cmd, getreg32(KINETIS_SDHC_IRQSTAT)); cmd, getreg32(KINETIS_SDHC_IRQSTAT));
+4 -2
View File
@@ -1694,7 +1694,9 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
return ret; return ret;
} }
/* If Controller doesn't need DMA before Write then send CMD */ /* If Controller does not need DMA setup before the write then send CMD24
* now.
*/
if ((priv->caps & SDIO_CAPS_DMABEFOREWRITE) == 0) if ((priv->caps & SDIO_CAPS_DMABEFOREWRITE) == 0)
{ {
@@ -1737,7 +1739,7 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
priv->wrbusy = true; priv->wrbusy = true;
/* If Controller needs DMA before Write then only send CMD now */ /* If Controller needs DMA setup before write then only send CMD24 now. */
if ((priv->caps & SDIO_CAPS_DMABEFOREWRITE) != 0) if ((priv->caps & SDIO_CAPS_DMABEFOREWRITE) != 0)
{ {