Redesign SDIO wait logic; add SDIO DMA logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2261 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2009-11-16 15:37:11 +00:00
parent b1742905ff
commit 2740d04258
3 changed files with 421 additions and 223 deletions

View File

@ -49,6 +49,7 @@
#include "chip.h"
#include "up_arch.h"
#include "stm32_internal.h"
#include "stm32_dma.h"
#include "stm32_sdio.h"
#if CONFIG_STM32_SDIO
@ -64,6 +65,10 @@
# undef CONFIG_SDIO_DMA
#endif
#ifndef CONFIG_SDIO_DMAPRIO
# define CONFIG_SDIO_DMAPRIO DMA_CCR_PRIMED
#endif
/* Friendly CLKCR bit re-definitions ****************************************/
#define SDIO_CLKCR_RISINGEDGE (0)
@ -88,6 +93,13 @@
#define SDIO_CMDTIMEOUT 100000
#define SDIO_LONGTIMEOUT 0x7fffffff
/* DMA CCR register settings */
#define SDIO_RXDMA16_CONFIG (CONFIG_SDIO_DMAPRIO|DMA_CCR_MSIZE_16BITS|\
DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC)
#define SDIO_TXDMA16_CONFIG (CONFIG_SDIO_DMAPRIO|DMA_CCR_MSIZE_16BITS|\
DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC|DMA_CCR_DIR)
/****************************************************************************
* Private Types
****************************************************************************/
@ -100,7 +112,17 @@ struct stm32_dev_s
/* STM32-specific extensions */
ubyte type; /* Card type (see MMCSD_CARDTYPE_ definitions) */
sem_t eventsem; /* Implements event waiting */
sdio_event_t waitevents; /* Set of events to be waited for */
volatile sdio_event_t wkupevents; /* Set of events that caused the wakeup */
sdio_event_t cbevents; /* Set of events to be cause callbacks */
sdio_mediachange_t callback; /* Registered callback function */
/* DMA support */
#ifdef CONFIG_SDIO_DMA
DMA_HANDLE dma; /* Handle for DMA channel */
#endif
};
/****************************************************************************
@ -109,6 +131,8 @@ struct stm32_dev_s
/* Low-level helpers ********************************************************/
static void stm32_takesem(struct stm32_dev_s *priv);
#define stm32_givesem(priv) (sem_post(&priv->waitsem))
static inline void stm32_setclkcr(uint32 clkcr);
static inline void stm32_enableint(uint32 bitset);
static inline void stm32_disableint(uint32 bitset);
@ -119,7 +143,9 @@ static inline void stm32_clkdisable(void)
/* DMA Helpers **************************************************************/
static inline void stm32_dmaenable(void);
#ifdef CONFIG_SDIO_DMA
static void stm32_dmacallback(DMA_HANDLE handle, ubyte isr, void *arg);
#endif
/* Data Transfer Helpers ****************************************************/
@ -155,10 +181,11 @@ static int stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer);
/* EVENT handler */
static void stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset,
static void stm32_waitenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset,
boolean enable);
static ubyte stm32_eventwait(FAR struct sdio_dev_s *dev, uint32 timeout);
static ubyte stm32_events(FAR struct sdio_dev_s *dev);
static void stm32_callbackenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset);
static int stm32_registercallback(FAR struct sdio_dev_s *dev,
sdio_mediachange_t callback, void *arg)
@ -166,23 +193,18 @@ static int stm32_registercallback(FAR struct sdio_dev_s *dev,
#ifdef CONFIG_SDIO_DMA
static boolean stm32_dmasupported(FAR struct sdio_dev_s *dev);
#ifdef CONFIG_DATA_CACHE
static void stm32_coherent(FAR struct sdio_dev_s *dev, FAR void *addr,
size_t len, boolean write);
#endif
static int stm32_dmareadsetup(FAR struct sdio_dev_s *dev,
FAR ubyte *buffer);
FAR ubyte *buffer, size_t buflen);
static int stm32_dmawritesetup(FAR struct sdio_dev_s *dev,
FAR const ubyte *buffer);
static int stm32_dmaenable(FAR struct sdio_dev_s *dev);
FAR const ubyte *buffer, size_t buflen);
static int stm32_dmastart(FAR struct sdio_dev_s *dev);
static int stm32_dmastop(FAR struct sdio_dev_s *dev);
static int stm32_dmastatus(FAR struct sdio_dev_s *dev,
size_t *remaining);
#endif
/* Initialization/uninitialization/reset ************************************/
static void stm32_callback(void *arg);
static void stm32_default(void);
/****************************************************************************
@ -211,19 +233,16 @@ struct stm32_dev_s g_mmcsd =
.recvR7 = stm32_recvshort,
.recvsetup = stm32_recvsetup,
.recvdata = stm32_recvdata,
.eventenable = stm32_eventenable,
.waitenable = stm32_waitenable,
.eventwait = stm32_eventwait,
.events = stm32_events,
.callbackenable = stm32_callbackenable,
.registercallback = stm32_registercallback,
#ifdef CONFIG_SDIO_DMA
.dmasupported = stm32_dmasupported,
#ifdef CONFIG_DATA_CACHE
.coherent = stm32_coherent,
#endif
.dmareadsetup = stm32_dmareadsetup,
.dmawritesetup = stm32_dmawritesetup,
.dmaenable = stm32_dmaenable,
.dmastart = stm32_dmastart,
.dmastop = stm32_dmastop,
.dmastatus = stm32_dmastatus,
#endif
},
@ -236,6 +255,35 @@ struct stm32_dev_s g_mmcsd =
/****************************************************************************
* Low-level Helpers
****************************************************************************/
/****************************************************************************
* Name: stm32_takesem
*
* Description:
* Take the wait semaphore (handling false alarm wakeups due to the receipt
* of signals).
*
* Input Parameters:
* dev - Instance of the SDIO device driver state structure.
*
* Returned Value:
* None
*
****************************************************************************/
static void stm32_takesem(struct stm32_dev_s *priv)
{
/* Take the semaphore (perhaps waiting) */
while (sem_wait(&priv->waitsem) != 0)
{
/* The only case that an error should occr here is if the wait was
* awakened by a signal.
*/
ASSERT(errno == EINTR);
}
}
/****************************************************************************
* Name: stm32_setclkcr
*
@ -374,10 +422,31 @@ static inline void stm32_clkdisable(void)
/****************************************************************************
* DMA Helpers
****************************************************************************/
static inline void stm32_dmaenable(void)
/****************************************************************************
* Name: stm32_dmacallback
*
* Description:
* Called when SDIO DMA completes
*
****************************************************************************/
#ifdef CONFIG_SDIO_DMA
static void stm32_dmacallback(DMA_HANDLE handle, ubyte isr, void *arg)
{
putreg32(1, SDIO_DCTRL_DMAEN_BB);
FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)arg;
/* Is a data transfer complete event expected? */
if ((priv->waitevents & SDIOWAIT_TRANSFERDONE) != 0)
{
/* Yes, wake up the waiting thread */
priv->wkupevent = SDIOWAIT_TRANSFERDONE;
sdio_semgive(priv);
}
}
#endif
/****************************************************************************
* Data Transfer Helpers
@ -1008,14 +1077,22 @@ static int stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
}
/****************************************************************************
* Name: stm32_eventenable
* Name: stm32_waitenable
*
* Description:
* Enable/disable notification of a set of MMC/SD events
* Enable/disable of a set of MMC/SD wait events. This is part of the
* the SDIO_WAITEVENT sequence. The set of to-be-waited-for events is
* configured before calling stm32_waitevent. This is done in this way
* to help the driver to eliminate race conditions between the command
* setup and the subsequent events.
*
* The enabled events persist until either (1) SDIO_WAITENABLE is called
* again specifying a different set of wait events, or (2) SDIO_EVENTWAIT
* returns.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* eventset - A bitset of events to enable or disable (see MMCSDEVENT_*
* eventset - A bitset of events to enable or disable (see SDIOWAIT_*
* definitions). 0=disable; 1=enable.
*
* Returned Value:
@ -1023,15 +1100,26 @@ static int stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
*
****************************************************************************/
static void stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
static void stm32_waitenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
{
struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
/* This odd sequence avoids race conditions */
DEBUGASSERT(priv != NULL);
priv->waitevents = 0;
priv->wkupevents = 0;
priv->waitevents = eventset;
}
/****************************************************************************
* Name: stm32_eventwait
*
* Description:
* Wait for one of the enabled events to occur (or a timeout)
* Wait for one of the enabled events to occur (or a timeout). Note that
* all events enabled by SDIO_WAITEVENTS are disabled when stm32_eventwait
* returns. SDIO_WAITEVENTS must be called again before stm32_eventwait
* can be used again.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
@ -1046,7 +1134,41 @@ static void stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
static ubyte stm32_eventwait(FAR struct sdio_dev_s *dev, uint32 timeout)
{
return 0;
ubyte wkupevents = 0;
DEBUGASSERT(priv->waitevents != 0);
/* Loop until the event (or the timeout occurs). Race conditions are avoided
* by calling stm32_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!
*/
#warning "Timeout logic not implemented"
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.
*/
stm32_takesem(priv);
/* Check if the event has occurred. */
wkupevents = (ubyte)(priv->wkupevents & priv->waitevents)
if (wkupevents != 0)
{
/* Yes... break out of the loop with wkupevents non-zero */
break;
}
}
/* Clear all enabled wait events before returning */
priv->waitevents = 0;
priv->wkupevents = 0;
return wkupevents;
}
/****************************************************************************
@ -1070,6 +1192,36 @@ static ubyte stm32_events(FAR struct sdio_dev_s *dev)
return 0;
}
/****************************************************************************
* Name: stm32_callbackenable
*
* Description:
* Enable/disable of a set of MMC/SD callback events. This is part of the
* the SDIO callback sequence. The set of events is configured to enabled
* callbacks to the function provided in stm32_registercallback.
*
* Events are automatically disabled once the callback is performed and no
* further callback events will occur until they are again enabled by
* calling this methos.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* eventset - A bitset of events to enable or disable (see SDIOMEDIA_*
* definitions). 0=disable; 1=enable.
*
* Returned Value:
* None
*
****************************************************************************/
static void stm32_callbackenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
{
struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
DEBUGASSERT(priv != NULL);
priv->cbevents = eventset;
stm32_callback(priv);
}
/****************************************************************************
* Name: stm32_registercallback
*
@ -1079,6 +1231,9 @@ static ubyte stm32_events(FAR struct sdio_dev_s *dev)
* interrupt level events should be handled by calling back on the work
* thread.
*
* When this method is called, all callbacks should be disabled until they
* are enabled via a call to SDIO_CALLBACKENABLE
*
* Input Parameters:
* dev - Device-specific state data
* callback - The funtion to call on the media change
@ -1092,7 +1247,15 @@ static ubyte stm32_events(FAR struct sdio_dev_s *dev)
static int stm32_registercallback(FAR struct sdio_dev_s *dev,
sdio_mediachange_t callback, void *arg)
{
return -ENOSYS;
struct stm32_dev_s *priv = (struct stm32_dev_s*)dev;
/* Disable callbacks and register this callback and is argument */
DEBUGASSERT(priv != NULL);
priv->cbevents = 0;
priv->cbarg = arg;
priv->callback = callback;
return OK;
}
/****************************************************************************
@ -1116,44 +1279,19 @@ static boolean stm32_dmasupported(FAR struct sdio_dev_s *dev)
}
#endif
/****************************************************************************
* Name: stm32_coherent
*
* Description:
* If the processor supports a data cache, then this method will make sure
* that the contents of the DMA memory and the data cache are coherent in
* preparation for the DMA transfer. For write transfers, this may mean
* flushing the data cache, for read transfers this may mean invalidating
* the data cache.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* addr - The beginning address of the DMA
* len - The length of the DMA
* write - TRUE: A write DMA will be performed; FALSE: a read DMA will be
* performed.
*
* Returned Value:
* None
*
****************************************************************************/
#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_DATA_CACHE)
static void stm32_coherent(FAR struct sdio_dev_s *dev, FAR void *addr,
size_t len, boolean write)
{
}
#endif
/****************************************************************************
* Name: stm32_dmareadsetup
*
* Description:
* Setup to perform a read DMA
* Setup to perform a read DMA. If the processor supports a data cache,
* then this method will also make sure that the contents of the DMA memory
* and the data cache are coherent. For read transfers this may mean
* invalidating the data cache.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* buffer - The memory to DMA from
* buflen - The size of the DMA transfer in bytes
*
* Returned Value:
* OK on success; a negated errno on failure
@ -1161,9 +1299,12 @@ static void stm32_coherent(FAR struct sdio_dev_s *dev, FAR void *addr,
****************************************************************************/
#ifdef CONFIG_SDIO_DMA
static int tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
static int tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer, size_t buflen)
{
return -ENOSYS;
/* Configure the RX DMA */
stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32)buffer,
(buflen + 3) >> 2, SDIO_RXDMA16_CONFIG);
}
#endif
@ -1171,11 +1312,15 @@ static int tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
* Name: stm32_dmawritesetup
*
* Description:
* Setup to perform a write DMA
* Setup to perform a write DMA. If the processor supports a data cache,
* then this method will also make sure that the contents of the DMA memory
* and the data cache are coherent. For write transfers, this may mean
* flushing the data cache.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* buffer - The memory to DMA into
* buflen - The size of the DMA transfer in bytes
*
* Returned Value:
* OK on success; a negated errno on failure
@ -1184,9 +1329,12 @@ static int tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
#ifdef CONFIG_SDIO_DMA
static int stm32_dmawritesetup(FAR struct sdio_dev_s *dev,
FAR const ubyte *buffer)
FAR const ubyte *buffer, size_t buflen)
{
return -ENOSYS;
/* Configure the RX DMA */
stm32_dmasetup(priv->dma, STM32_SDIO_FIFO, (uint32)buffer,
(buflen + 3) >> 2, SDIO_TXDMA16_CONFIG);
}
#endif
@ -1207,28 +1355,7 @@ static int stm32_dmawritesetup(FAR struct sdio_dev_s *dev,
#ifdef CONFIG_SDIO_DMA
static int stm32_dmastart(FAR struct sdio_dev_s *dev)
{
return -ENOSYS;
}
#endif
/****************************************************************************
* Name: stm32_dmastop
*
* Description:
* Stop the DMA
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
*
* Returned Value:
* OK on success; a negated errno on failure
*
****************************************************************************/
#ifdef CONFIG_SDIO_DMA
static int stm32_dmastop(FAR struct sdio_dev_s *dev)
{
return -ENOSYS;
stm32_dmastart(priv->dma, sdio_dmacallback, priv, FALSE);
}
#endif
@ -1236,7 +1363,7 @@ static int stm32_dmastop(FAR struct sdio_dev_s *dev)
* Name: stm32_dmastatus
*
* Description:
* Returnt the number of bytes remaining in the DMA transfer
* Return the number of bytes remaining in the DMA transfer
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
@ -1268,6 +1395,63 @@ static int stm32_dmastatus(FAR struct sdio_dev_s *dev, size_t *remaining)
/****************************************************************************
* Initialization/uninitialization/reset
****************************************************************************/
/****************************************************************************
* Name: stm32_callback
*
* Description:
* Perform callback.
*
* Assumptions:
* This function does not execute in the context of an interrupt handler.
* It may be invoked on any user thread or scheduled on the work thread
* from an interrupt handler.
*
****************************************************************************/
static void stm32_callback(void *arg)
{
struct stm32_dev_s *priv = (struct stm32_dev_s*)arg;
/* Is a callback registered? */
DEBUGASSERT(priv != NULL);
if (priv->callback)
{
/* Yes.. Check for enabled callback events */
if ((stm32_status(&priv->dev) & SDIO_STATUS_PRESENT) != 0)
{
/* Media is present. Is the media inserted event enabled? */
if ((priv->cbevents & SDIOMEDIA_INSERTED) == 0)
{
/* No... return without performing the callback */
return;
}
}
else
{
/* Media is not present. Is the media eject event enabled? */
if ((priv->cbevents & SDIOMEDIA_EJECTED) == 0)
{
/* No... return without performing the callback */
return;
}
}
/* Perform the callback, disabling further callbacks. Of course, the
* the callback can (and probably should) re-enable callbacks.
*/
priv->cbevents = 0;
priv->callback(priv->cbarg);
}
}
/****************************************************************************
* Name: stm32_default
*
@ -1294,24 +1478,35 @@ static void stm32_default(void)
****************************************************************************/
/****************************************************************************
* Name: mmcsd_slotinitialize
* Name: sdio_initialize
*
* Description:
* Initialize one slot for operation using the MMC/SD interface
* Initialize SDIO for operation.
*
* Input Parameters:
* minor - The MMC/SD minor device number. The MMC/SD device will be
* registered as /dev/mmcsdN where N is the minor number
* slotno - The slot number to use. This is only meaningful for architectures
* that support multiple MMC/SD slots. This value must be in the range
* {0, ..., CONFIG_MMCSD_NSLOTS}.
* dev - And instance of an MMC/SD interface. The MMC/SD hardware should
* be initialized and ready to use.
* slotno - Not used.
*
* Returned Values:
* A reference to an SDIO interface structure. NULL is returned on failures.
*
****************************************************************************/
int mmcsd_slotinitialize(int minor, int slotno, FAR struct sdio_dev_s *dev)
FAR sdio_dev_s *mmcsd_slotinitialize(int slotno)
{
/* There is only one, slot */
struct stm32_dev_s *priv = &g_sdiodev;
/* Initialize the SDIO slot structure */
sem_init(&priv->eventsem, 0, 0);
/* Allocate a DMA channel */
#ifdef CONFIG_SDIO_DMA
priv->dma = stm32_dmachannel(DMACHAN_SDIO);
#endif
/* Configure GPIOs for 4-bit, wide-bus operation (the chip is capable of
* 8-bit wide bus operation but D4-D7 are not configured).
*/
@ -1333,7 +1528,7 @@ int mmcsd_slotinitialize(int minor, int slotno, FAR struct sdio_dev_s *dev)
stm32_setpwrctrl(SDIO_POWER_PWRCTRL_ON);
stm32_clkenable(ENABLE);
return -ENOSYS;
return &g_sdiodev.dev;
}
#endif /* CONFIG_STM32_SDIO */

View File

@ -372,7 +372,7 @@ static int mmcsd_getSCR(struct mmcsd_state_s *priv, uint32 scr[2])
/* Send ACMD51 SD_APP_SEND_SCR with argument as 0 to start data receipt */
(void)SDIO_EVENTENABLE(priv->dev, SDIOEVENT_READDATADONE);
(void)SDIO_WAITENABLE(priv->dev, SDIOWAIT_TRANSFERDONE);
mmcsd_sendcmdpoll(priv, SD_ACMD51, 0);
ret = mmcsd_recvR1(priv, SD_ACMD51);
if (ret != OK)
@ -1063,6 +1063,10 @@ static int mmcsd_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
{
fdbg("ERROR: mmcsd_removed failed: %d\n", ret);
}
/* Enable logic to detect if a card is re-inserted */
SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
}
break;
@ -1117,6 +1121,10 @@ static void mmcsd_mediachange(FAR void *arg)
*/
(void)mmcsd_removed(priv);
/* Enable logic to detect if a card is re-inserted */
SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
}
mmcsd_givesem(priv);
}
@ -1743,7 +1751,7 @@ static int mmcsd_probe(struct mmcsd_state_s *priv)
if (ret != OK)
{
fdbg("ERROR: Failed to initialize card: %d\n");
SDIO_EVENTENABLE(priv->dev, SDIOEVENT_INSERTED);
SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
}
else
{
@ -1780,7 +1788,7 @@ static int mmcsd_probe(struct mmcsd_state_s *priv)
/* Set up to receive asynchronous, media removal events */
SDIO_EVENTENABLE(priv->dev, SDIOEVENT_EJECTED);
SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_EJECTED);
}
}
@ -1793,7 +1801,7 @@ static int mmcsd_probe(struct mmcsd_state_s *priv)
/* There is no card in the slot */
fvdbg("No card\n");
SDIO_EVENTENABLE(priv->dev, SDIOEVENT_INSERTED);
SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
ret = -ENODEV;
}
@ -1835,10 +1843,6 @@ static int mmcsd_removed(struct mmcsd_state_s *priv)
/* Disable clocking to the card */
(void)SDIO_CLOCK(priv->dev, CLOCK_SDIO_DISABLED);
/* Enable logic to detect if a card is re-inserted */
SDIO_EVENTENABLE(priv->dev, SDIOEVENT_INSERTED);
return OK;
}
@ -1874,7 +1878,7 @@ static int mmcsd_hwinitialize(struct mmcsd_state_s *priv)
fvdbg("Successfully attached MMC/SD interrupts\n");
/* Register a callback so that we get informed if media is inserted or
* removed from the slot.
* removed from the slot (Initially all callbacks are disabled).
*/
SDIO_REGISTERCALLBACK(priv->dev, mmcsd_mediachange, (FAR void *)priv);
@ -1917,7 +1921,7 @@ static int mmcsd_hwinitialize(struct mmcsd_state_s *priv)
{
/* No... Setup to receive the media inserted event */
SDIO_EVENTENABLE(priv->dev, SDIOEVENT_INSERTED);
SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
/* ENODEV is returned to indicate that no card is inserted in the slot. */

View File

@ -47,18 +47,21 @@
* Pre-Processor Definitions
****************************************************************************/
/* MMC/SD events needed by the driver */
/* MMC/SD events needed by the driver
*
* Wait events are used for event-waiting by SDIO_WAITENABLE and SDIO_EVENTWAIT
*/
#define SDIOEVENT_EJECTED (1 << 0) /* Bit 0: CD/DAT3 transition low, media removed */
#define SDIOEVENT_INSERTED (1 << 1) /* Bit 1: CD/DAT3 transition high, media inserted */
#define SDIOEVENT_CMDDONE (1 << 2) /* Bit 2: Command+response complete */
#define SDIOEVENT_READCMDDONE (1 << 3) /* Bit 3: Read command done */
#define SDIOEVENT_WRITECMDDONE (1 << 4) /* Bit 4: Write command done */
#define SDIOEVENT_READDATADONE (1 << 5) /* Bit 5: Read data done */
#define SDIOEVENT_WRITEDATADONE (1 << 6) /* Bit 6: Write data done */
#define SDIOEVENT_CMDBUSYDONE (1 << 7) /* Bit 7: Command with transition to not busy */
#define SDIOWAIT_CMDDONE (1 << 0) /* Bit 0: Command+response complete */
#define SDIOWAIT_CMDBUSYDONE (1 << 1) /* Bit 1: Command with transition to not busy */
#define SDIOWAIT_TRANSFERDONE (1 << 2) /* Bit 2: Data transfer/DMA done */
#define SDIOEVENT_ALLEVENTS 0xff
#define SDIOWAIT_ALLEVENTS 0x03
/* Media events are used for enable/disable registered event callbacks */
#define SDIOMEDIA_EJECTED (1 << 0) /* Bit 0: Mmedia removed */
#define SDIOMEDIA_INSERTED (1 << 1) /* Bit 1: Media inserted */
/* Commands are bit-encoded to provide as much information to the SDIO driver as
* possible in 32-bits. The encoding is as follows:
@ -517,14 +520,22 @@
#define SDIO_RECVDATA(dev,buffer) ((dev)->recvdata(dev,buffer))
/****************************************************************************
* Name: SDIO_EVENTENABLE
* Name: SDIO_WAITENABLE
*
* Description:
* Enable/disable notification of a set of MMC/SD events
* Enable/disable of a set of MMC/SD wait events. This is part of the
* the SDIO_WAITEVENT sequence. The set of to-be-waited-for events is
* configured before calling SDIO_EVENTWAIT. This is done in this way
* to help the driver to eliminate race conditions between the command
* setup and the subsequent events.
*
* The enabled events persist until either (1) SDIO_WAITENABLE is called
* again specifying a different set of wait events, or (2) SDIO_EVENTWAIT
* returns.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* eventset - A bitset of events to enable or disable (see MMCSDEVENT_*
* eventset - A bitset of events to enable or disable (see SDIOWAIT_*
* definitions). 0=disable; 1=enable.
*
* Returned Value:
@ -532,13 +543,16 @@
*
****************************************************************************/
#define SDIO_EVENTENABLE(dev,eventset) ((dev)->eventenable(dev,eventset))
#define SDIO_WAITENABLE(dev,eventset) ((dev)->waitenable(dev,eventset))
/****************************************************************************
* Name: SDIO_EVENTWAIT
*
* Description:
* Wait for one of the enabled events to occur (or a timeout)
* Wait for one of the enabled events to occur (or a timeout). Note that
* all events enabled by SDIO_WAITEVENTS are disabled when SDIO_EVENTWAIT
* returns. SDIO_WAITEVENTS must be called again before SDIO_EVENTWAIT
* can be used again.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
@ -571,6 +585,30 @@
#define SDIO_EVENTS(dev) ((dev)->events(dev))
/****************************************************************************
* Name: SDIO_CALLBACKENABLE
*
* Description:
* Enable/disable of a set of MMC/SD callback events. This is part of the
* the SDIO callback sequence. The set of events is configured to enabled
* callbacks to the function provided in SDIO_REGISTERCALLBACK.
*
* Events are automatically disabled once the callback is performed and no
* further callback events will occur until they are again enabled by
* calling this methos.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* eventset - A bitset of events to enable or disable (see SDIOMEDIA_*
* definitions). 0=disable; 1=enable.
*
* Returned Value:
* None
*
****************************************************************************/
#define SDIO_CALLBACKENABLE(dev,eventset) ((dev)->waitenable(dev,eventset))
/****************************************************************************
* Name: SDIO_REGISTERCALLBACK
*
@ -580,6 +618,9 @@
* interrupt level events should be handled by calling back on the work
* thread.
*
* When this method is called, all callbacks should be disabled until they
* are enabled via a call to SDIO_CALLBACKENABLE
*
* Input Parameters:
* dev - Device-specific state data
* callback - The funtion to call on the media change
@ -612,43 +653,19 @@
# define SDIO_DMASUPPORTED(dev) (FALSE)
#endif
/****************************************************************************
* Name: SDIO_COHERENT
*
* Description:
* If the processor supports a data cache, then this method will make sure
* that the contents of the DMA memory and the data cache are coherent in
* preparation for the DMA transfer. For write transfers, this may mean
* flushing the data cache, for read transfers this may mean invalidating
* the data cache.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* addr - The beginning address of the DMA
* len - The length of the DMA
* write - TRUE: A write DMA will be performed; FALSE: a read DMA will be
* performed.
*
* Returned Value:
* None
*
****************************************************************************/
#if defined(CONFIG_SDIO_DMA) && defined(CONFIG_DATA_CACHE)
# define SDIO_COHERENT(dev,addr,len,write) ((dev)->coherent(dev,addr,len,write))
#else
# define SDIO_COHERENT(dev,addr,len,write)
#endif
/****************************************************************************
* Name: SDIO_DMAREADSETUP
*
* Description:
* Setup to perform a read DMA
* Setup to perform a read DMA. If the processor supports a data cache,
* then this method will also make sure that the contents of the DMA memory
* and the data cache are coherent. For read transfers this may mean
* invalidating the data cache.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* buffer - The memory to DMA from
* buflen - The size of the DMA transfer in bytes
*
* Returned Value:
* OK on success; a negated errno on failure
@ -656,20 +673,24 @@
****************************************************************************/
#ifdef CONFIG_SDIO_DMA
# define SDIO_DMAREADSETUP(dev,buffer) ((dev)->dmareadsetup(dev,buffer))
# define SDIO_DMAREADSETUP(dev,buffer,len) ((dev)->dmareadsetup(dev,buffer,len))
#else
# define SDIO_DMAREADSETUP(dev,buffer) (-ENOSYS)
# define SDIO_DMAREADSETUP(dev,buffer,len) (-ENOSYS)
#endif
/****************************************************************************
* Name: SDIO_DMAWRITESETUP
*
* Description:
* Setup to perform a write DMA
* Setup to perform a write DMA. If the processor supports a data cache,
* then this method will also make sure that the contents of the DMA memory
* and the data cache are coherent. For write transfers, this may mean
* flushing the data cache.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* buffer - The memory to DMA into
* buflen - The size of the DMA transfer in bytes
*
* Returned Value:
* OK on success; a negated errno on failure
@ -677,9 +698,9 @@
****************************************************************************/
#ifdef CONFIG_SDIO_DMA
# define SDIO_DMAWRITESETUP(dev,buffer) ((dev)->dmawritesetup(dev,buffer))
# define SDIO_DMAWRITESETUP(dev,buffer,len) ((dev)->dmawritesetup(dev,buffer,len))
#else
# define SDIO_DMAWRITESETUP(dev,buffer) (-ENOSYS)
# define SDIO_DMAWRITESETUP(dev,buffer,len) (-ENOSYS)
#endif
/****************************************************************************
@ -702,31 +723,11 @@
# define SDIO_DMASTART(dev) (-ENOSYS)
#endif
/****************************************************************************
* Name: SDIO_DMASTOP
*
* Description:
* Stop the DMA
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
*
* Returned Value:
* OK on success; a negated errno on failure
*
****************************************************************************/
#ifdef CONFIG_SDIO_DMA
# define SDIO_DMASTOP(dev) ((dev)->dmastop(dev))
#else
# define SDIO_DMASTOP(dev) (-ENOSYS)
#endif
/****************************************************************************
* Name: SDIO_DMASTATUS
*
* Description:
* Returnt the number of bytes remaining in the DMA transfer
* Return the number of bytes remaining in the DMA transfer
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
@ -810,7 +811,7 @@ struct sdio_dev_s
/* EVENT handler */
void (*eventenable)(FAR struct sdio_dev_s *dev, sdio_eventset_t eventset);
void (*waitenable)(FAR struct sdio_dev_s *dev, sdio_eventset_t eventset);
ubyte (*eventwait)(FAR struct sdio_dev_s *dev, uint32 timeout);
ubyte (*events)(FAR struct sdio_dev_s *dev);
int (*registercallback)(FAR struct sdio_dev_s *dev, sdio_mediachange_t callback, void *arg);
@ -819,13 +820,11 @@ struct sdio_dev_s
#ifdef CONFIG_SDIO_DMA
boolean (*dmasupported)(FAR struct sdio_dev_s *dev);
#ifdef CONFIG_DATA_CACHE
void (*coherent)(FAR struct sdio_dev_s *dev, FAR void *addr, size_t len, boolean write);
#endif
int (*dmareadsetup)(FAR struct sdio_dev_s *dev, FAR ubyte *buffer);
int (*dmawritesetup)(FAR struct sdio_dev_s *dev, FAR const ubyte *buffer);
int (*dmaenable)(FAR struct sdio_dev_s *dev);
int (*dmastop)(FAR struct sdio_dev_s *dev);
int (*dmareadsetup)(FAR struct sdio_dev_s *dev, FAR ubyte *buffer,
size_t buflen);
int (*dmawritesetup)(FAR struct sdio_dev_s *dev, FAR const ubyte *buffer,
size_t buflen);
int (*dmastart)(FAR struct sdio_dev_s *dev);
int (*dmastatus)(FAR struct sdio_dev_s *dev, size_t *remaining);
#endif
};