arch/arm/samv7: fix random corruption of data after SDIO RX DMA transaction
use time based timeout calculation instead of cycle based
minor styling fixes
#undef HSCMI_NORXDMA /* Define to disable RX DMA */
#undef HSCMI_NOTXDMA /* Define to disable TX DMA */
-/* Timing */
+/* Timing : 100mS short timeout, 2 seconds for long one */
-#define HSMCI_CMDTIMEOUT (100000)
-#define HSMCI_LONGTIMEOUT (0x7fffffff)
+#define HSMCI_CMDTIMEOUT MSEC2TICK(100)
+#define HSMCI_LONGTIMEOUT MSEC2TICK(2000)
/* Big DTIMER setting */
@@ -409,7 +409,8 @@ static inline void sam_putreg(struct sam_dev_s *priv, uint32_t value,
unsigned int offset);
static inline void sam_configwaitints(struct sam_dev_s *priv,
- uint32_t waitmask, sdio_eventset_t waitevents);
+ uint32_t waitmask,
+ sdio_eventset_t waitevents);
static void sam_disablewaitints(struct sam_dev_s *priv,
sdio_eventset_t wkupevent);
static inline void sam_configxfrints(struct sam_dev_s *priv,
@@ -1572,6 +1573,21 @@ static int sam_hsmci_interrupt(int irq, void *context, void *arg)
else
{
+ /* If buffer is not NULL that means that RX DMA is finished.
+ * We need to invalidate RX buffer
+ */
+
+ if (priv->buffer != NULL)
+ {
+ DEBUGASSERT(priv->remaining > 0);
+
+ up_invalidate_dcache((uintptr_t)priv->buffer,
+ (uintptr_t)priv->buffer +
+ priv->remaining);
+ priv->buffer = NULL;
+ priv->remaining = 0;
+ }
+
/* End the transfer */
sam_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
@@ -2388,6 +2404,7 @@ static int sam_waitresponse(struct sdio_dev_s *dev, uint32_t cmd)
struct sam_dev_s *priv = (struct sam_dev_s *)dev;
uint32_t sr;
uint32_t pending;
+ clock_t watchtime;
int32_t timeout;
switch (cmd & MMCSD_RESPONSE_MASK)
@@ -2415,6 +2432,7 @@ static int sam_waitresponse(struct sdio_dev_s *dev, uint32_t cmd)
/* Then wait for the response (or timeout) */
+ watchtime = clock_systime_ticks();
for (; ; )
{
/* Did a Command-Response sequence termination event occur? */
@@ -2464,7 +2482,7 @@ static int sam_waitresponse(struct sdio_dev_s *dev, uint32_t cmd)
return OK;
}
}
- else if (--timeout <= 0)
+ else if (clock_systime_ticks() - watchtime > timeout)
{
mcerr("ERROR: Timeout cmd: %08" PRIx32 " events: %08" PRIx32
" SR: %08" PRIx32 "\n",
@@ -3011,6 +3029,8 @@ static int sam_dmarecvsetup(struct sdio_dev_s *dev, uint8_t *buffer,
priv->dmabusy = true;
priv->xfrbusy = true;
priv->txbusy = false;
+ priv->buffer = (uint32_t *)buffer;
+ priv->remaining = buflen;
sam_dmastart(priv->dma, sam_dmacallback, priv);
/* Configure transfer-related interrupts. Transfer interrupts are not
