From d501ffc563979f3d8170497a978306ba82cf637a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Recht=C3=A9?= Date: Thu, 9 Feb 2017 11:28:30 -0600 Subject: [PATCH] Kinetis SDHC driver fixes. --- arch/arm/src/kinetis/kinetis_sdhc.c | 79 +++++++++++++---------------- drivers/mmcsd/mmcsd_sdio.c | 6 ++- 2 files changed, 38 insertions(+), 47 deletions(-) diff --git a/arch/arm/src/kinetis/kinetis_sdhc.c b/arch/arm/src/kinetis/kinetis_sdhc.c index 6f0c71a3ec..b0682f8733 100644 --- a/arch/arm/src/kinetis/kinetis_sdhc.c +++ b/arch/arm/src/kinetis/kinetis_sdhc.c @@ -116,10 +116,10 @@ # endif #endif -/* Timing */ +/* Timing in ms for commands wait response */ -#define SDHC_CMDTIMEOUT (100000) -#define SDHC_LONGTIMEOUT (0x7fffffff) +#define SDHC_CMDTIMEOUT MSEC2TICK(100) +#define SDHC_LONGTIMEOUT MSEC2TICK(500) /* 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 */ -#ifdef CONFIG_KINETIS_SDHC_DMA /* 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 @@ -715,32 +714,6 @@ static void kinetis_dataconfig(struct kinetis_dev_s *priv, bool bwrite, 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]; } data; - /* Loop while there is more data to be sent, waiting for buffer write - * ready (BWR) + /* Loop while there is more data to be sent, while buffer write enable + * (PRSSTAT.BWEN) */ mcinfo("Entry: remaining: %d IRQSTAT: %08x\n", priv->remaining, getreg32(KINETIS_SDHC_IRQSTAT)); 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? */ 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); } + /* 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", 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 caps |= SDIO_CAPS_DMASUPPORTED; #endif + caps |= SDIO_CAPS_DMABEFOREWRITE; 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 cmdidx; - int32_t timeout; /* 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; + start = clock_systimer(); + 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", 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) { + systime_t timeout; + systime_t start; + systime_t elapsed; uint32_t errors; - int32_t timeout; - int ret = OK; + int ret = OK; 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). */ + start = clock_systimer(); + 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", cmd, getreg32(KINETIS_SDHC_IRQSTAT)); diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c index c17d9eb39d..8ededac175 100644 --- a/drivers/mmcsd/mmcsd_sdio.c +++ b/drivers/mmcsd/mmcsd_sdio.c @@ -1694,7 +1694,9 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, 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) { @@ -1737,7 +1739,7 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, 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) {