arch/arm/src/lpc54xx/lpc54_sdmmc.c: Ported the last of Dave Marples fixes to the LPC54. Not yet verified.
This commit is contained in:
parent
d1c01e1135
commit
c6a480f8ff
@ -256,7 +256,6 @@ config LPC43_SDMMC
|
|||||||
default n
|
default n
|
||||||
select ARCH_HAVE_SDIO
|
select ARCH_HAVE_SDIO
|
||||||
select SDIO_BLOCKSETUP
|
select SDIO_BLOCKSETUP
|
||||||
depends on EXPERIMENTAL
|
|
||||||
|
|
||||||
config LPC43_SPI
|
config LPC43_SPI
|
||||||
bool "SPI"
|
bool "SPI"
|
||||||
|
@ -128,10 +128,10 @@
|
|||||||
# error "Driver requires CONFIG_SDIO_BLOCKSETUP to be set"
|
# error "Driver requires CONFIG_SDIO_BLOCKSETUP to be set"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Timing */
|
/* Timing : 100mS short timeout, 2 seconds for long one */
|
||||||
|
|
||||||
#define SDCARD_CMDTIMEOUT (10000)
|
#define SDCARD_CMDTIMEOUT MSEC2TICK(100)
|
||||||
#define SDCARD_LONGTIMEOUT (0x7fffffff)
|
#define SDCARD_LONGTIMEOUT MSEC2TICK(2000)
|
||||||
|
|
||||||
/* Type of Card Bus Size */
|
/* Type of Card Bus Size */
|
||||||
|
|
||||||
@ -621,28 +621,36 @@ static inline void lpc54_sdcard_clock(bool enable)
|
|||||||
* arg - The argument to use with the command.
|
* arg - The argument to use with the command.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* None
|
* Returns zero on success. One will be returned on a timeout.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int lpc54_ciu_sendcmd(uint32_t cmd, uint32_t arg)
|
static int lpc54_ciu_sendcmd(uint32_t cmd, uint32_t arg)
|
||||||
{
|
{
|
||||||
volatile int32_t tmo = SDCARD_CMDTIMEOUT;
|
clock_t watchtime;
|
||||||
|
|
||||||
mcinfo("cmd=%04lx arg=%04lx\n", (unsigned long)cmd, (unsigned long)arg);
|
mcinfo("cmd=%04lx arg=%04lx\n", (unsigned long)cmd, (unsigned long)arg);
|
||||||
|
DEBUGASSERT((lpc54_getreg(LPC54_SDMMC_CMD) & SDMMC_CMD_STARTCMD) == 0);
|
||||||
|
|
||||||
/* Set command arg reg */
|
/* Set command arg reg */
|
||||||
|
|
||||||
lpc54_putreg(arg, LPC54_SDMMC_CMDARG);
|
lpc54_putreg(arg, LPC54_SDMMC_CMDARG);
|
||||||
lpc54_putreg(SDMMC_CMD_STARTCMD | cmd, LPC54_SDMMC_CMD);
|
lpc54_putreg(SDMMC_CMD_STARTCMD | cmd, LPC54_SDMMC_CMD);
|
||||||
|
|
||||||
/* Poll until command is accepted by the CIU */
|
/* Poll until command is accepted by the CIU, or we timeout */
|
||||||
|
|
||||||
while (--tmo > 0 && (lpc54_getreg(LPC54_SDMMC_CMD) & SDMMC_CMD_STARTCMD) != 0)
|
watchtime = clock_systimer();
|
||||||
|
|
||||||
|
while ((lpc54_getreg(LPC54_SDMMC_CMD) & SDMMC_CMD_STARTCMD) != 0)
|
||||||
{
|
{
|
||||||
|
if (watchtime - clock_systimer() > SDCARD_CMDTIMEOUT)
|
||||||
|
{
|
||||||
|
mcerr("TMO Timed out (%08X)\n",lpc54_getreg(LPC54_SDMMC_CMD));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (tmo < 1) ? 1 : 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -1031,7 +1039,6 @@ static int lpc54_sdmmc_interrupt(int irq, void *context, FAR void *arg)
|
|||||||
|
|
||||||
/* Transfer data to the TX FIFO */
|
/* Transfer data to the TX FIFO */
|
||||||
|
|
||||||
mcinfo("Write FIFO\n");
|
|
||||||
DEBUGASSERT(priv->wrdir);
|
DEBUGASSERT(priv->wrdir);
|
||||||
|
|
||||||
for (status = lpc54_getreg(LPC54_SDMMC_STATUS);
|
for (status = lpc54_getreg(LPC54_SDMMC_STATUS);
|
||||||
@ -1043,20 +1050,6 @@ static int lpc54_sdmmc_interrupt(int irq, void *context, FAR void *arg)
|
|||||||
priv->buffer++;
|
priv->buffer++;
|
||||||
priv->remaining -= 4;
|
priv->remaining -= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If all of the data has been transferred to the FIFO, then
|
|
||||||
* disable further TX data requests and wait for the data end
|
|
||||||
* event.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (priv->remaining <= 0)
|
|
||||||
{
|
|
||||||
uint32_t intmask = lpc54_getreg(LPC54_SDMMC_INTMASK);
|
|
||||||
intmask &= ~SDMMC_INT_TXDR;
|
|
||||||
lpc54_putreg(intmask, LPC54_SDMMC_INTMASK);
|
|
||||||
|
|
||||||
priv->xfrmask &= ~SDMMC_INT_TXDR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if ((pending & SDMMC_INT_RXDR) != 0)
|
else if ((pending & SDMMC_INT_RXDR) != 0)
|
||||||
{
|
{
|
||||||
@ -1064,7 +1057,6 @@ static int lpc54_sdmmc_interrupt(int irq, void *context, FAR void *arg)
|
|||||||
|
|
||||||
/* Transfer data from the RX FIFO */
|
/* Transfer data from the RX FIFO */
|
||||||
|
|
||||||
mcinfo("Read from FIFO\n");
|
|
||||||
DEBUGASSERT(!priv->wrdir);
|
DEBUGASSERT(!priv->wrdir);
|
||||||
|
|
||||||
for (status = lpc54_getreg(LPC54_SDMMC_STATUS);
|
for (status = lpc54_getreg(LPC54_SDMMC_STATUS);
|
||||||
@ -1076,18 +1068,6 @@ static int lpc54_sdmmc_interrupt(int irq, void *context, FAR void *arg)
|
|||||||
priv->buffer++;
|
priv->buffer++;
|
||||||
priv->remaining -= 4;
|
priv->remaining -= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If all of the data has been transferred to the FIFO, then
|
|
||||||
* just force DTO event processing (the DTO interrupt is not
|
|
||||||
* actually even enabled in this use case).
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (priv->remaining <= 0)
|
|
||||||
{
|
|
||||||
/* Force the DTO event */
|
|
||||||
|
|
||||||
pending |= SDMMC_INT_DTO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for transfer errors */
|
/* Check for transfer errors */
|
||||||
@ -1348,7 +1328,7 @@ static void lpc54_reset(FAR struct sdio_dev_s *dev)
|
|||||||
|
|
||||||
/* Define MAX Timeout */
|
/* Define MAX Timeout */
|
||||||
|
|
||||||
lpc54_putreg(SDCARD_LONGTIMEOUT, LPC54_SDMMC_TMOUT);
|
lpc54_putreg(0x7fffffff, LPC54_SDMMC_TMOUT);
|
||||||
|
|
||||||
/* Disable clock to CIU (needs latch) */
|
/* Disable clock to CIU (needs latch) */
|
||||||
|
|
||||||
@ -1763,6 +1743,10 @@ static int lpc54_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
lpc54_putreg(regval, LPC54_SDMMC_CTRL);
|
lpc54_putreg(regval, LPC54_SDMMC_CTRL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Flush ints before we start */
|
||||||
|
|
||||||
|
lpc54_putreg(SDCARD_TRANSFER_ALL, LPC54_SDMMC_RINTSTS);
|
||||||
|
|
||||||
/* Configure the transfer interrupts */
|
/* Configure the transfer interrupts */
|
||||||
|
|
||||||
lpc54_config_xfrints(priv, SDCARD_RECV_MASK);
|
lpc54_config_xfrints(priv, SDCARD_RECV_MASK);
|
||||||
@ -1827,6 +1811,10 @@ static int lpc54_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer
|
|||||||
lpc54_putreg(regval, LPC54_SDMMC_CTRL);
|
lpc54_putreg(regval, LPC54_SDMMC_CTRL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Flush ints before we start */
|
||||||
|
|
||||||
|
lpc54_putreg(SDCARD_TRANSFER_ALL, LPC54_SDMMC_RINTSTS);
|
||||||
|
|
||||||
/* Configure the transfer interrupts */
|
/* Configure the transfer interrupts */
|
||||||
|
|
||||||
lpc54_config_xfrints(priv, SDCARD_SEND_MASK);
|
lpc54_config_xfrints(priv, SDCARD_SEND_MASK);
|
||||||
@ -1894,6 +1882,7 @@ static int lpc54_cancel(FAR struct sdio_dev_s *dev)
|
|||||||
static int lpc54_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
|
static int lpc54_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
|
||||||
{
|
{
|
||||||
volatile int32_t timeout;
|
volatile int32_t timeout;
|
||||||
|
clock_t watchtime;
|
||||||
uint32_t events;
|
uint32_t events;
|
||||||
|
|
||||||
mcinfo("cmd=%04x\n", cmd);
|
mcinfo("cmd=%04x\n", cmd);
|
||||||
@ -1933,13 +1922,15 @@ static int lpc54_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
|
|||||||
|
|
||||||
/* Then wait for the response (or timeout or error) */
|
/* Then wait for the response (or timeout or error) */
|
||||||
|
|
||||||
|
watchtime = clock_systimer();
|
||||||
while ((lpc54_getreg(LPC54_SDMMC_RINTSTS) & events) != events)
|
while ((lpc54_getreg(LPC54_SDMMC_RINTSTS) & events) != events)
|
||||||
{
|
{
|
||||||
if (--timeout <= 0)
|
if (clock_systimer() - watchtime > timeout)
|
||||||
{
|
{
|
||||||
mcerr("ERROR: Timeout cmd: %04x events: %04x STA: %08x RINTSTS: %08x\n",
|
mcerr("ERROR: Timeout cmd: %04x events: %04x STA: %08x RINTSTS: %08x\n",
|
||||||
cmd, events, lpc54_getreg(LPC54_SDMMC_STATUS),
|
cmd, events, lpc54_getreg(LPC54_SDMMC_STATUS),
|
||||||
lpc54_getreg(LPC54_SDMMC_RINTSTS));
|
lpc54_getreg(LPC54_SDMMC_RINTSTS));
|
||||||
|
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
else if ((lpc54_getreg(LPC54_SDMMC_RINTSTS) & SDCARD_INT_RESPERR) != 0)
|
else if ((lpc54_getreg(LPC54_SDMMC_RINTSTS) & SDCARD_INT_RESPERR) != 0)
|
||||||
@ -1947,6 +1938,7 @@ static int lpc54_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
|
|||||||
mcerr("ERROR: SDMMC failure cmd: %04x events: %04x STA: %08x RINTSTS: %08x\n",
|
mcerr("ERROR: SDMMC failure cmd: %04x events: %04x STA: %08x RINTSTS: %08x\n",
|
||||||
cmd, events, lpc54_getreg(LPC54_SDMMC_STATUS),
|
cmd, events, lpc54_getreg(LPC54_SDMMC_STATUS),
|
||||||
lpc54_getreg(LPC54_SDMMC_RINTSTS));
|
lpc54_getreg(LPC54_SDMMC_RINTSTS));
|
||||||
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2545,7 +2537,11 @@ static int lpc54_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
|
|
||||||
lpc54_putreg((uint32_t)&g_sdmmc_dmadd[0], LPC54_SDMMC_DBADDR);
|
lpc54_putreg((uint32_t)&g_sdmmc_dmadd[0], LPC54_SDMMC_DBADDR);
|
||||||
|
|
||||||
/* Enable internal DMA, burst size of 4, fixed burst */
|
/* Flush ints before we start */
|
||||||
|
|
||||||
|
lpc54_putreg(SDCARD_TRANSFER_ALL, LPC54_SDMMC_RINTSTS);
|
||||||
|
|
||||||
|
/* Enable internal DMA, burst size of 4, fixed burst */
|
||||||
|
|
||||||
regval = lpc54_getreg(LPC54_SDMMC_CTRL);
|
regval = lpc54_getreg(LPC54_SDMMC_CTRL);
|
||||||
regval |= SDMMC_CTRL_INTDMA;
|
regval |= SDMMC_CTRL_INTDMA;
|
||||||
@ -2691,7 +2687,11 @@ static int lpc54_dmasendsetup(FAR struct sdio_dev_s *dev,
|
|||||||
|
|
||||||
lpc54_putreg((uint32_t) &g_sdmmc_dmadd[0], LPC54_SDMMC_DBADDR);
|
lpc54_putreg((uint32_t) &g_sdmmc_dmadd[0], LPC54_SDMMC_DBADDR);
|
||||||
|
|
||||||
/* Enable internal DMA, burst size of 4, fixed burst */
|
/* Flush ints before we start */
|
||||||
|
|
||||||
|
lpc54_putreg(SDCARD_TRANSFER_ALL, LPC54_SDMMC_RINTSTS);
|
||||||
|
|
||||||
|
/* Enable internal DMA, burst size of 4, fixed burst */
|
||||||
|
|
||||||
regval = lpc54_getreg(LPC54_SDMMC_CTRL);
|
regval = lpc54_getreg(LPC54_SDMMC_CTRL);
|
||||||
regval |= SDMMC_CTRL_INTDMA;
|
regval |= SDMMC_CTRL_INTDMA;
|
||||||
|
@ -112,6 +112,9 @@ STATUS
|
|||||||
of the time. I still get CRC errors when writing and I have not
|
of the time. I still get CRC errors when writing and I have not
|
||||||
successfully written to the SD card. It is closer but more TLC is
|
successfully written to the SD card. It is closer but more TLC is
|
||||||
needed.
|
needed.
|
||||||
|
2018-10-24: Dave Marples now has the LPC43 SD/MMC working reliably. I
|
||||||
|
have ported all of Dave's change to the LPC54 but have done no further
|
||||||
|
testing as of this writing. The feature is still marked EXPERIMENTAL.
|
||||||
|
|
||||||
There is still no support for the Accelerometer, SPIFI, or USB. There is
|
There is still no support for the Accelerometer, SPIFI, or USB. There is
|
||||||
a complete but not entirely functional SD card driver and and tested SPI
|
a complete but not entirely functional SD card driver and and tested SPI
|
||||||
|
Loading…
Reference in New Issue
Block a user