Kinetis lpc sdcard (#719)

* Check return of nxsem_wait_uninterruptible
* Fix nxstyle reported errors

Note: It will not pass on CI tests because of it:

    .recvR1           = lpc17_40_recvshortcrc,
    .recvR2           = lpc17_40_recvlong,
    .recvR3           = lpc17_40_recvshort,
    .recvR4           = lpc17_40_recvnotimpl,
    .recvR5           = lpc17_40_recvnotimpl,
    .recvR6           = lpc17_40_recvshortcrc,
    .recvR7           = lpc17_40_recvshort,
This commit is contained in:
Alan Carvalho de Assis 2020-04-03 23:25:14 -03:00 committed by Gregory Nutt
parent df1eeb8e3f
commit 460124629c

View File

@ -74,6 +74,7 @@
****************************************************************************/
/* Configuration ************************************************************/
/* Required system configuration options:
*
* CONFIG_ARCH_DMA - Enable architecture-specific DMA subsystem
@ -87,9 +88,10 @@
* CONFIG_SDIO_MUXBUS - Setting this configuration enables some locking
* APIs to manage concurrent accesses on the SD card bus. This is not
* needed for the simple case of a single SD card, for example.
* CONFIG_LPC17_40_SDCARD_DMA - Enable SD card DMA. This is a marginally optional.
* For most usages, SD accesses will cause data overruns if used without DMA.
* NOTE the above system DMA configuration options.
* CONFIG_LPC17_40_SDCARD_DMA - Enable SD card DMA. This is a marginally
* optional.
* For most usages, SD accesses will cause data overruns if used without
* DMA. NOTE the above system DMA configuration options.
* CONFIG_LPC17_40_SDCARD_WIDTH_D1_ONLY - This may be selected to force the
* driver operate with only a single data line (the default is to use
* all 4 SD data lines).
@ -239,13 +241,14 @@ struct lpc17_40_dev_s
struct sdio_dev_s dev; /* Standard, base SD card interface */
/* LPC17XX_40XX-specific extensions */
/* Event support */
sem_t waitsem; /* Implements event waiting */
sdio_eventset_t waitevents; /* Set of events to be waited for */
uint32_t waitmask; /* Interrupt enables for event waiting */
sem_t waitsem; /* Implements event waiting */
sdio_eventset_t waitevents; /* Set of events to be waited for */
uint32_t waitmask; /* Interrupt enables for event waiting */
volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */
WDOG_ID waitwdog; /* Watchdog that handles event timeouts */
WDOG_ID waitwdog; /* Watchdog that handles event timeouts */
/* Callback support */
@ -302,12 +305,14 @@ struct lpc17_40_sampleregs_s
/* Low-level helpers ********************************************************/
static void lpc17_40_takesem(struct lpc17_40_dev_s *priv);
static int lpc17_40_takesem(struct lpc17_40_dev_s *priv);
#define lpc17_40_givesem(priv) (nxsem_post(&priv->waitsem))
static inline void lpc17_40_setclock(uint32_t clkcr);
static void lpc17_40_configwaitints(struct lpc17_40_dev_s *priv, uint32_t waitmask,
sdio_eventset_t waitevents, sdio_eventset_t wkupevents);
static void lpc17_40_configxfrints(struct lpc17_40_dev_s *priv, uint32_t xfrmask);
static void lpc17_40_configwaitints(struct lpc17_40_dev_s *priv,
uint32_t waitmask, sdio_eventset_t waitevents,
sdio_eventset_t wkupevents);
static void lpc17_40_configxfrints(struct lpc17_40_dev_s *priv,
uint32_t xfrmask);
static void lpc17_40_setpwrctrl(uint32_t pwrctrl);
static inline uint32_t lpc17_40_getpwrctrl(void);
@ -317,7 +322,8 @@ static inline uint32_t lpc17_40_getpwrctrl(void);
static void lpc17_40_sampleinit(void);
static void lpc17_40_sdcard_sample(struct lpc17_40_sdcard_regs_s *regs);
static void lpc17_40_sample(struct lpc17_40_dev_s *priv, int index);
static void lpc17_40_sdcard_dump(struct lpc17_40_sdcard_regs_s *regs, const char *msg);
static void lpc17_40_sdcard_dump(struct lpc17_40_sdcard_regs_s *regs,
const char *msg);
static void lpc17_40_dumpsample(struct lpc17_40_dev_s *priv,
struct lpc17_40_sampleregs_s *regs, const char *msg);
static void lpc17_40_dumpsamples(struct lpc17_40_dev_s *priv);
@ -334,13 +340,16 @@ static void lpc17_40_dmacallback(DMA_HANDLE handle, void *arg, int status);
/* Data Transfer Helpers ****************************************************/
static uint8_t lpc17_40_log2(uint16_t value);
static void lpc17_40_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl);
static void lpc17_40_dataconfig(uint32_t timeout, uint32_t dlen,
uint32_t dctrl);
static void lpc17_40_datadisable(void);
static void lpc17_40_sendfifo(struct lpc17_40_dev_s *priv);
static void lpc17_40_recvfifo(struct lpc17_40_dev_s *priv);
static void lpc17_40_eventtimeout(int argc, uint32_t arg);
static void lpc17_40_endwait(struct lpc17_40_dev_s *priv, sdio_eventset_t wkupevent);
static void lpc17_40_endtransfer(struct lpc17_40_dev_s *priv, sdio_eventset_t wkupevent);
static void lpc17_40_endwait(struct lpc17_40_dev_s *priv,
sdio_eventset_t wkupevent);
static void lpc17_40_endtransfer(struct lpc17_40_dev_s *priv,
sdio_eventset_t wkupevent);
/* Interrupt Handling *******************************************************/
@ -368,8 +377,8 @@ static int lpc17_40_attach(FAR struct sdio_dev_s *dev);
static int lpc17_40_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t arg);
static int lpc17_40_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
size_t nbytes);
static int lpc17_40_recvsetup(FAR struct sdio_dev_s *dev,
FAR uint8_t *buffer, size_t nbytes);
static int lpc17_40_sendsetup(FAR struct sdio_dev_s *dev,
FAR const uint8_t *buffer, uint32_t nbytes);
static int lpc17_40_cancel(FAR struct sdio_dev_s *dev);
@ -467,6 +476,7 @@ static struct lpc17_40_sampleregs_s g_sampleregs[DEBUG_NSAMPLES];
/****************************************************************************
* Low-level Helpers
****************************************************************************/
/****************************************************************************
* Name: lpc17_40_takesem
*
@ -482,9 +492,9 @@ static struct lpc17_40_sampleregs_s g_sampleregs[DEBUG_NSAMPLES];
*
****************************************************************************/
static void lpc17_40_takesem(struct lpc17_40_dev_s *priv)
static int lpc17_40_takesem(struct lpc17_40_dev_s *priv)
{
nxsem_wait_uninterruptible(&priv->waitsem);
return nxsem_wait_uninterruptible(&priv->waitsem);
}
/****************************************************************************
@ -545,9 +555,10 @@ static inline void lpc17_40_setclock(uint32_t clkcr)
*
****************************************************************************/
static void lpc17_40_configwaitints(struct lpc17_40_dev_s *priv, uint32_t waitmask,
sdio_eventset_t waitevents,
sdio_eventset_t wkupevent)
static void lpc17_40_configwaitints(struct lpc17_40_dev_s *priv,
uint32_t waitmask,
sdio_eventset_t waitevents,
sdio_eventset_t wkupevent)
{
irqstate_t flags;
@ -581,7 +592,8 @@ static void lpc17_40_configwaitints(struct lpc17_40_dev_s *priv, uint32_t waitma
*
****************************************************************************/
static void lpc17_40_configxfrints(struct lpc17_40_dev_s *priv, uint32_t xfrmask)
static void lpc17_40_configxfrints(struct lpc17_40_dev_s *priv,
uint32_t xfrmask)
{
irqstate_t flags;
flags = enter_critical_section();
@ -594,8 +606,8 @@ static void lpc17_40_configxfrints(struct lpc17_40_dev_s *priv, uint32_t xfrmask
* Name: lpc17_40_setpwrctrl
*
* Description:
* Change the PWRCTRL field of the SD card POWER register to turn the SD card
* ON or OFF
* Change the PWRCTRL field of the SD card POWER register to turn the
* SD card ON or OFF
*
* Input Parameters:
* clkcr - A new PWRCTRL setting
@ -657,7 +669,8 @@ static inline uint32_t lpc17_40_getpwrctrl(void)
#ifdef CONFIG_DEBUG_MEMCARD_INFO
static void lpc17_40_sampleinit(void)
{
memset(g_sampleregs, 0xff, DEBUG_NSAMPLES * sizeof(struct lpc17_40_sampleregs_s));
memset(g_sampleregs, 0xff, DEBUG_NSAMPLES *
sizeof(struct lpc17_40_sampleregs_s));
}
#endif
@ -716,7 +729,8 @@ static void lpc17_40_sample(struct lpc17_40_dev_s *priv, int index)
****************************************************************************/
#ifdef CONFIG_DEBUG_MEMCARD_INFO
static void lpc17_40_sdcard_dump(struct lpc17_40_sdcard_regs_s *regs, const char *msg)
static void lpc17_40_sdcard_dump(struct lpc17_40_sdcard_regs_s *regs,
const char *msg)
{
mcinfo("SD Card Registers: %s\n", msg);
mcinfo(" POWER[%08x]: %08x\n", LPC17_40_SDCARD_PWR, regs->pwr);
@ -741,7 +755,8 @@ static void lpc17_40_sdcard_dump(struct lpc17_40_sdcard_regs_s *regs, const char
#ifdef CONFIG_DEBUG_MEMCARD_INFO
static void lpc17_40_dumpsample(struct lpc17_40_dev_s *priv,
struct lpc17_40_sampleregs_s *regs, const char *msg)
struct lpc17_40_sampleregs_s *regs,
const char *msg)
{
#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_LPC17_40_SDCARD_DMA)
if (priv->dmamode)
@ -749,6 +764,7 @@ static void lpc17_40_dumpsample(struct lpc17_40_dev_s *priv,
lpc17_40_dmadump(priv->dma, &regs->dma, msg);
}
#endif
lpc17_40_sdcard_dump(&regs->sdcard, msg);
}
#endif
@ -764,19 +780,25 @@ static void lpc17_40_dumpsample(struct lpc17_40_dev_s *priv,
#ifdef CONFIG_DEBUG_MEMCARD_INFO
static void lpc17_40_dumpsamples(struct lpc17_40_dev_s *priv)
{
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP], "Before setup");
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP],
"Before setup");
#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_LPC17_40_SDCARD_DMA)
if (priv->dmamode)
{
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_ENABLE], "Before DMA enable");
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_ENABLE],
"Before DMA enable");
}
#endif
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP], "After setup");
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER], "End of transfer");
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP],
"After setup");
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER],
"End of transfer");
#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_LPC17_40_SDCARD_DMA)
if (priv->dmamode)
{
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_DMA_CALLBACK], "DMA Callback");
lpc17_40_dumpsample(priv, &g_sampleregs[SAMPLENDX_DMA_CALLBACK],
"DMA Callback");
}
#endif
}
@ -797,9 +819,9 @@ static void lpc17_40_dmacallback(DMA_HANDLE handle, void *arg, int status)
DEBUGASSERT(priv->dmamode);
sdio_eventset_t result;
/* In the normal case, SD card appears to handle the End-Of-Transfer interrupt
* first with the End-Of-DMA event occurring significantly later. On
* transfer errors, however, the DMA error will occur before the End-of-
/* In the normal case, SD card appears to handle the End-Of-Transfer
* interrupt first with the End-Of-DMA event occurring significantly later.
* On transfer errors, however, the DMA error will occur before the End-of-
* Transfer.
*/
@ -809,7 +831,8 @@ static void lpc17_40_dmacallback(DMA_HANDLE handle, void *arg, int status)
if (status < 0)
{
dmaerr("ERROR: DMA error %d, remaining: %d\n", status, priv->remaining);
dmaerr("ERROR: DMA error %d, remaining: %d\n", status,
priv->remaining);
result = SDIOWAIT_ERROR;
}
else
@ -874,7 +897,8 @@ static uint8_t lpc17_40_log2(uint16_t value)
*
****************************************************************************/
static void lpc17_40_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl)
static void lpc17_40_dataconfig(uint32_t timeout, uint32_t dlen,
uint32_t dctrl)
{
uint32_t regval = 0;
@ -1067,7 +1091,8 @@ static void lpc17_40_eventtimeout(int argc, uint32_t arg)
/* There is always race conditions with timer expirations. */
DEBUGASSERT((priv->waitevents & SDIOWAIT_TIMEOUT) != 0 || priv->wkupevent != 0);
DEBUGASSERT((priv->waitevents & SDIOWAIT_TIMEOUT) != 0 ||
priv->wkupevent != 0);
/* Is a data transfer complete event expected? */
@ -1098,7 +1123,8 @@ static void lpc17_40_eventtimeout(int argc, uint32_t arg)
*
****************************************************************************/
static void lpc17_40_endwait(struct lpc17_40_dev_s *priv, sdio_eventset_t wkupevent)
static void lpc17_40_endwait(struct lpc17_40_dev_s *priv,
sdio_eventset_t wkupevent)
{
/* Cancel the watchdog timeout */
@ -1133,7 +1159,8 @@ static void lpc17_40_endwait(struct lpc17_40_dev_s *priv, sdio_eventset_t wkupev
*
****************************************************************************/
static void lpc17_40_endtransfer(struct lpc17_40_dev_s *priv, sdio_eventset_t wkupevent)
static void lpc17_40_endtransfer(struct lpc17_40_dev_s *priv,
sdio_eventset_t wkupevent)
{
/* Disable all transfer related interrupts */
@ -1153,8 +1180,8 @@ static void lpc17_40_endtransfer(struct lpc17_40_dev_s *priv, sdio_eventset_t wk
lpc17_40_sample(priv, SAMPLENDX_END_TRANSFER);
/* Make sure that the DMA is stopped (it will be stopped automatically
* on normal transfers, but not necessarily when the transfer terminates
* on an error condition).
* on normal transfers, but not necessarily when the transfer
* terminates on an error condition).
*/
lpc17_40_dmastop(priv->dma);
@ -1206,7 +1233,8 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
* bits remaining, then we have work to do here.
*/
while ((enabled = getreg32(LPC17_40_SDCARD_STATUS) & getreg32(LPC17_40_SDCARD_MASK0)) != 0)
while ((enabled = getreg32(LPC17_40_SDCARD_STATUS) &
getreg32(LPC17_40_SDCARD_MASK0)) != 0)
{
/* Handle in progress, interrupt driven data transfers ****************/
@ -1219,7 +1247,7 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
{
/* Is the RX FIFO half full or more? Is so then we must be
* processing a receive transaction.
*/
*/
if ((pending & SDCARD_STATUS_RXFIFOHF) != 0)
{
@ -1228,9 +1256,9 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
lpc17_40_recvfifo(priv);
}
/* Otherwise, Is the transmit FIFO half empty or less? If so we must
* be processing a send transaction. NOTE: We can't be processing
* both!
/* Otherwise, Is the transmit FIFO half empty or less? If so
* we must be processing a send transaction. NOTE: We can't be
* processing both!
*/
else if ((pending & SDCARD_STATUS_TXFIFOHE) != 0)
@ -1293,8 +1321,10 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
{
/* Terminate the transfer with an error */
mcerr("ERROR: Data block CRC failure, remaining: %d\n", priv->remaining);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
mcerr("ERROR: Data block CRC failure, remaining: %d\n",
priv->remaining);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE |
SDIOWAIT_ERROR);
}
/* Handle data timeout error */
@ -1304,7 +1334,8 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
/* Terminate the transfer with an error */
mcerr("ERROR: Data timeout, remaining: %d\n", priv->remaining);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE |
SDIOWAIT_TIMEOUT);
}
/* Handle RX FIFO overrun error */
@ -1313,8 +1344,10 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
{
/* Terminate the transfer with an error */
mcerr("ERROR: RX FIFO overrun, remaining: %d\n", priv->remaining);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
mcerr("ERROR: RX FIFO overrun, remaining: %d\n",
priv->remaining);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE |
SDIOWAIT_ERROR);
}
/* Handle TX FIFO underrun error */
@ -1323,8 +1356,10 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
{
/* Terminate the transfer with an error */
mcerr("ERROR: TX FIFO underrun, remaining: %d\n", priv->remaining);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
mcerr("ERROR: TX FIFO underrun, remaining: %d\n",
priv->remaining);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE |
SDIOWAIT_ERROR);
}
/* Handle start bit error */
@ -1334,7 +1369,8 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
/* Terminate the transfer with an error */
mcerr("ERROR: Start bit, remaining: %d\n", priv->remaining);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE | SDIOWAIT_ERROR);
lpc17_40_endtransfer(priv, SDIOWAIT_TRANSFERDONE |
SDIOWAIT_ERROR);
}
}
@ -1353,7 +1389,8 @@ static int lpc17_40_interrupt(int irq, void *context, FAR void *arg)
{
/* Yes.. wake the thread up */
putreg32(SDCARD_RESPDONE_ICR | SDCARD_CMDDONE_ICR, LPC17_40_SDCARD_CLEAR);
putreg32(SDCARD_RESPDONE_ICR | SDCARD_CMDDONE_ICR,
LPC17_40_SDCARD_CLEAR);
lpc17_40_endwait(priv, SDIOWAIT_RESPONSEDONE);
}
}
@ -1566,7 +1603,8 @@ static void lpc17_40_widebus(FAR struct sdio_dev_s *dev, bool wide)
*
****************************************************************************/
static void lpc17_40_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
static void lpc17_40_clock(FAR struct sdio_dev_s *dev,
enum sdio_clock_e rate)
{
uint32_t clkcr;
@ -1635,7 +1673,6 @@ static int lpc17_40_attach(FAR struct sdio_dev_s *dev)
ret = irq_attach(LPC17_40_IRQ_MCI, lpc17_40_interrupt, NULL);
if (ret == OK)
{
/* Disable all interrupts at the SD card controller and clear static
* interrupt flags
*/
@ -1669,7 +1706,8 @@ static int lpc17_40_attach(FAR struct sdio_dev_s *dev)
*
****************************************************************************/
static int lpc17_40_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
static int lpc17_40_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t arg)
{
uint32_t regval;
uint32_t cmdidx;
@ -1730,8 +1768,9 @@ static int lpc17_40_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t a
* (interrupt driven mode). This method will do whatever controller setup
* is necessary. This would be called for SD memory just BEFORE sending
* CMD13 (SEND_STATUS), CMD17 (READ_SINGLE_BLOCK), CMD18
* (READ_MULTIPLE_BLOCKS), ACMD51 (SEND_SCR), etc. Normally, SDCARD_WAITEVENT
* will be called to receive the indication that the transfer is complete.
* (READ_MULTIPLE_BLOCKS), ACMD51 (SEND_SCR), etc. Normally,
* SDCARD_WAITEVENT will be called to receive the indication that the
* transfer is complete.
*
* Input Parameters:
* dev - An instance of the SD card device interface
@ -1743,8 +1782,9 @@ static int lpc17_40_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t a
*
****************************************************************************/
static int lpc17_40_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
size_t nbytes)
static int lpc17_40_recvsetup(FAR struct sdio_dev_s *dev,
FAR uint8_t *buffer,
size_t nbytes)
{
struct lpc17_40_dev_s *priv = (struct lpc17_40_dev_s *)dev;
uint32_t dblocksize;
@ -1783,10 +1823,11 @@ static int lpc17_40_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
* Name: lpc17_40_sendsetup
*
* Description:
* Setup hardware in preparation for data transfer from the card. This method
* will do whatever controller setup is necessary. This would be called
* for SD memory just AFTER sending CMD24 (WRITE_BLOCK), CMD25
* (WRITE_MULTIPLE_BLOCK), ... and before SDCARD_SENDDATA is called.
* Setup hardware in preparation for data transfer from the card.
* This method will do whatever controller setup is necessary.
* This would be called for SD memory just AFTER sending
* CMD24 (WRITE_BLOCK), CMD25 (WRITE_MULTIPLE_BLOCK), ... and before
* SDCARD_SENDDATA is called.
*
* Input Parameters:
* dev - An instance of the SD card device interface
@ -1798,8 +1839,9 @@ static int lpc17_40_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
*
****************************************************************************/
static int lpc17_40_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer,
size_t nbytes)
static int lpc17_40_sendsetup(FAR struct sdio_dev_s *dev,
FAR const uint8_t *buffer,
size_t nbytes)
{
struct lpc17_40_dev_s *priv = (struct lpc17_40_dev_s *)dev;
uint32_t dblocksize;
@ -1838,9 +1880,9 @@ static int lpc17_40_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buf
*
* Description:
* Cancel the data transfer setup of SDCARD_RECVSETUP, SDCARD_SENDSETUP,
* SDCARD_DMARECVSETUP or SDCARD_DMASENDSETUP. This must be called to cancel
* the data transfer setup if, for some reason, you cannot perform the
* transfer.
* SDCARD_DMARECVSETUP or SDCARD_DMASENDSETUP. This must be called to
* cancel the data transfer setup if, for some reason, you cannot perform
* the transfer.
*
* Input Parameters:
* dev - An instance of the SD card device interface
@ -1875,8 +1917,8 @@ static int lpc17_40_cancel(FAR struct sdio_dev_s *dev)
if (priv->dmamode)
{
/* Make sure that the DMA is stopped (it will be stopped automatically
* on normal transfers, but not necessarily when the transfer terminates
* on an error condition.
* on normal transfers, but not necessarily when the transfer
* terminates on an error condition.
*/
lpc17_40_dmastop(priv->dma);
@ -1977,7 +2019,8 @@ static int lpc17_40_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
*
****************************************************************************/
static int lpc17_40_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort)
static int lpc17_40_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t *rshort)
{
#ifdef CONFIG_DEBUG_FEATURES
uint32_t respcmd;
@ -2007,7 +2050,6 @@ static int lpc17_40_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint3
* 0 1 End bit
*/
#ifdef CONFIG_DEBUG_FEATURES
if (!rshort)
{
@ -2046,7 +2088,8 @@ static int lpc17_40_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint3
/* Check response received is of desired command */
respcmd = getreg32(LPC17_40_SDCARD_RESPCMD);
if ((uint8_t)(respcmd & SDCARD_RESPCMD_MASK) != (cmd & MMCSD_CMDIDX_MASK))
if ((uint8_t)(respcmd & SDCARD_RESPCMD_MASK) !=
(cmd & MMCSD_CMDIDX_MASK))
{
mcerr("ERROR: RESCMD=%02x CMD=%08x\n", respcmd, cmd);
ret = -EINVAL;
@ -2062,7 +2105,8 @@ static int lpc17_40_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint3
return ret;
}
static int lpc17_40_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t rlong[4])
static int lpc17_40_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t rlong[4])
{
uint32_t regval;
int ret = OK;
@ -2116,7 +2160,8 @@ static int lpc17_40_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
return ret;
}
static int lpc17_40_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort)
static int lpc17_40_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t *rshort)
{
uint32_t regval;
int ret = OK;
@ -2159,12 +2204,14 @@ static int lpc17_40_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
{
*rshort = getreg32(LPC17_40_SDCARD_RESP0);
}
return ret;
}
/* MMC responses not supported */
static int lpc17_40_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rnotimpl)
static int lpc17_40_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t *rnotimpl)
{
putreg32(SDCARD_RESPDONE_ICR | SDCARD_CMDDONE_ICR, LPC17_40_SDCARD_CLEAR);
return -ENOSYS;
@ -2237,9 +2284,9 @@ static void lpc17_40_waitenable(FAR struct sdio_dev_s *dev,
*
* Description:
* Wait for one of the enabled events to occur (or a timeout). Note that
* all events enabled by SDCARD_WAITEVENTS are disabled when lpc17_40_eventwait
* returns. SDCARD_WAITEVENTS must be called again before lpc17_40_eventwait
* can be used again.
* all events enabled by SDCARD_WAITEVENTS are disabled when
* lpc17_40_eventwait returns. SDCARD_WAITEVENTS must be called again
* before lpc17_40_eventwait can be used again.
*
* Input Parameters:
* dev - An instance of the SD card device interface
@ -2290,7 +2337,8 @@ static sdio_eventset_t lpc17_40_eventwait(FAR struct sdio_dev_s *dev,
/* Start the watchdog timer */
delay = MSEC2TICK(timeout);
ret = wd_start(priv->waitwdog, delay, (wdentry_t)lpc17_40_eventtimeout,
ret = wd_start(priv->waitwdog, delay,
(wdentry_t) lpc17_40_eventtimeout,
1, (uint32_t)priv);
if (ret < 0)
{
@ -2298,24 +2346,35 @@ static sdio_eventset_t lpc17_40_eventwait(FAR struct sdio_dev_s *dev,
}
}
/* Loop until the event (or the timeout occurs). Race conditions are avoided
* by calling lpc17_40_waitenable prior to triggering the logic that will cause
* the wait to terminate. Under certain race conditions, the waited-for
* may have already occurred before this function was called!
/* Loop until the event (or the timeout occurs). Race conditions are
* avoided by calling lpc17_40_waitenable prior to triggering the logic
* that will cause the wait to terminate. Under certain race conditions,
* the waited-for may have already occurred before this function was
* called!
*/
for (; ; )
{
/* Wait for an event in event set to occur. If this the event has already
* occurred, then the semaphore will already have been incremented and
* there will be no wait.
/* Wait for an event in event set to occur. If this the event has
* already occurred, then the semaphore will already have been
* incremented and there will be no wait.
*/
lpc17_40_takesem(priv);
ret = lpc17_40_takesem(priv);
if (ret < 0)
{
wd_cancel(priv->waitwdog);
leave_critical_section(flags);
return SDIOWAIT_ERROR;
}
wkupevent = priv->wkupevent;
/* Check if the event has occurred. When the event has occurred, then
* evenset will be set to 0 and wkupevent will be set to a nonzero value.
* evenset will be set to 0 and wkupevent will be set to a nonzero
* value.
*/
if (wkupevent != 0)
@ -2344,8 +2403,8 @@ errout:
*
* Description:
* Enable/disable of a set of SD card callback events. This is part of the
* the SD card callback sequence. The set of events is configured to enabled
* callbacks to the function provided in lpc17_40_registercallback.
* the SD card callback sequence. The set of events is configured to
* enabled callbacks to the function provided in lpc17_40_registercallback.
*
* Events are automatically disabled once the callback is performed and no
* further callback events will occur until they are again enabled by
@ -2431,8 +2490,9 @@ static int lpc17_40_registercallback(FAR struct sdio_dev_s *dev,
****************************************************************************/
#ifdef CONFIG_LPC17_40_SDCARD_DMA
static int lpc17_40_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
size_t buflen)
static int lpc17_40_dmarecvsetup(FAR struct sdio_dev_s *dev,
FAR uint8_t *buffer,
size_t buflen)
{
struct lpc17_40_dev_s *priv = (struct lpc17_40_dev_s *)dev;
uint32_t dblocksize;
@ -2574,6 +2634,7 @@ static int lpc17_40_dmasendsetup(FAR struct sdio_dev_s *dev,
/****************************************************************************
* Initialization/uninitialization/reset
****************************************************************************/
/****************************************************************************
* Name: lpc17_40_callback
*
@ -2630,17 +2691,19 @@ static void lpc17_40_callback(void *arg)
priv->cbevents = 0;
/* Callbacks cannot be performed in the context of an interrupt handler.
* If we are in an interrupt handler, then queue the callback to be
* performed later on the work thread.
/* Callbacks cannot be performed in the context of an interrupt
* handler. If we are in an interrupt handler, then queue the
* callback to be performed later on the work thread.
*/
if (up_interrupt_context())
{
/* Yes.. queue it */
mcinfo("Queuing callback to %p(%p)\n", priv->callback, priv->cbarg);
work_queue(HPWORK, &priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
mcinfo("Queuing callback to %p(%p)\n", priv->callback,
priv->cbarg);
work_queue(HPWORK, &priv->cbwork, (worker_t)priv->callback,
priv->cbarg, 0);
}
else
{
@ -2687,7 +2750,8 @@ static void lpc17_40_default(void)
* slotno - Not used.
*
* Returned Value:
* A reference to an SD card interface structure. NULL is returned on failures.
* A reference to an SD card interface structure. NULL is returned on
* failures.
*
****************************************************************************/
@ -2706,6 +2770,7 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno)
putreg32(regval, LPC17_40_SYSCON_PCONP);
/* Initialize the SD card slot structure */
/* Initialize semaphores */
nxsem_init(&priv->waitsem, 0, 0);
@ -2795,6 +2860,7 @@ void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot)
{
priv->cdstatus &= ~SDIO_STATUS_PRESENT;
}
mcinfo("cdstatus OLD: %02x NEW: %02x\n", cdstatus, priv->cdstatus);
/* Perform any requested callback if the status has changed */