diff options
author | David Sidrane <david_s5@nscdg.com> | 2015-01-07 19:18:45 -1000 |
---|---|---|
committer | David Sidrane <david_s5@nscdg.com> | 2015-01-07 19:18:45 -1000 |
commit | 007dd93e6c3b99319ae0925846e7b44d50ac5275 (patch) | |
tree | 8d53b7ba27499df7d22d491ff66fc5271f89e15a | |
parent | 982650a1b30076732fee025a63ec151fc0f3dcb1 (diff) | |
download | px4-nuttx-007dd93e6c3b99319ae0925846e7b44d50ac5275.tar.gz px4-nuttx-007dd93e6c3b99319ae0925846e7b44d50ac5275.tar.bz2 px4-nuttx-007dd93e6c3b99319ae0925846e7b44d50ac5275.zip |
upstream plus sdio fixes sent to Greg
-rwxr-xr-x[-rw-r--r--] | nuttx/arch/arm/src/stm32/stm32_sdio.c | 79 | ||||
-rwxr-xr-x[-rw-r--r--] | nuttx/drivers/mmcsd/Kconfig | 26 | ||||
-rwxr-xr-x[-rw-r--r--] | nuttx/drivers/mmcsd/mmcsd_sdio.c | 17 | ||||
-rwxr-xr-x[-rw-r--r--] | nuttx/include/nuttx/sdio.h | 9 |
4 files changed, 122 insertions, 9 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_sdio.c b/nuttx/arch/arm/src/stm32/stm32_sdio.c index 4cdfe69eb..167e3d623 100644..100755 --- a/nuttx/arch/arm/src/stm32/stm32_sdio.c +++ b/nuttx/arch/arm/src/stm32/stm32_sdio.c @@ -400,6 +400,9 @@ static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupeven /* Interrupt Handling *******************************************************/ static int stm32_interrupt(int irq, void *context); +#ifdef CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE +static int stm32_rdyinterrupt(int irq, void *context); +#endif /* SDIO interface methods ***************************************************/ @@ -619,12 +622,40 @@ static void stm32_configwaitints(struct stm32_dev_s *priv, uint32_t waitmask, sdio_eventset_t wkupevent) { irqstate_t flags; +#ifdef CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE + int pinset; +#endif /* Save all of the data and set the new interrupt mask in one, atomic * operation. */ - flags = irqsave(); + +#ifdef CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE + if ((waitmask & SDIOWAIT_WRCOMPLETE) != 0) + { + + /* Do not use this in STM32_SDIO_MASK register */ + + waitmask &= !SDIOWAIT_WRCOMPLETE; + + pinset = GPIO_SDIO_D0 & (GPIO_PORT_MASK|GPIO_PIN_MASK); + pinset |= (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI); + + /* Arm the SDIO_D Ready and install Isr */ + + stm32_gpiosetevent(pinset, true, false, false, stm32_rdyinterrupt); + } + + /* Disarm SDIO_D ready */ + + if ((wkupevent & SDIOWAIT_WRCOMPLETE) != 0) + { + stm32_gpiosetevent(GPIO_SDIO_D0, false, false, false , NULL); + stm32_configgpio(GPIO_SDIO_D0); + + } +#endif priv->waitevents = waitevents; priv->wkupevent = wkupevent; priv->waitmask = waitmask; @@ -1237,7 +1268,28 @@ static void stm32_endtransfer(struct stm32_dev_s *priv, sdio_eventset_t wkupeven /**************************************************************************** * Interrrupt Handling ****************************************************************************/ +#ifdef CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE +/**************************************************************************** + * Name: stm32_rdyinterrupt + * + * Description: + * SDIO ready interrupt handler + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * + * Returned Value: + * None + * + ****************************************************************************/ +static int stm32_rdyinterrupt(int irq, void *context) +{ + struct stm32_dev_s *priv = &g_sdiodev; + stm32_endwait(priv, SDIOWAIT_WRCOMPLETE); + return OK; +} +#endif /**************************************************************************** * Name: stm32_interrupt * @@ -2236,6 +2288,14 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev, * interrupts. */ +#if defined(CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE) + if ((eventset & SDIOWAIT_WRCOMPLETE) != 0) + { + waitmask = SDIOWAIT_WRCOMPLETE; + } + else + { +#endif waitmask = 0; if ((eventset & SDIOWAIT_CMDDONE) != 0) { @@ -2255,6 +2315,9 @@ static void stm32_waitenable(FAR struct sdio_dev_s *dev, /* Enable event-related interrupts */ putreg32(SDIO_WAITALL_ICR, STM32_SDIO_ICR); +#if defined(CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE) + } +#endif stm32_configwaitints(priv, waitmask, eventset, 0); } @@ -2324,6 +2387,20 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, } } +#if defined(CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE) + if ((priv->waitevents & SDIOWAIT_WRCOMPLETE) != 0) + { + + /* Atomically read pin to see if ready (true) and determine if ISR fired + * If Pin is ready and if ISR did NOT fire end the wait here + */ + + if (stm32_gpioread(GPIO_SDIO_D0) && ((priv->wkupevent & SDIOWAIT_WRCOMPLETE) == 0)) + { + stm32_endwait(priv, SDIOWAIT_WRCOMPLETE); + } + } +#endif /* 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 diff --git a/nuttx/drivers/mmcsd/Kconfig b/nuttx/drivers/mmcsd/Kconfig index 4949cee1f..10cd5d9d1 100644..100755 --- a/nuttx/drivers/mmcsd/Kconfig +++ b/nuttx/drivers/mmcsd/Kconfig @@ -32,11 +32,27 @@ config MMCSD_MMCSUPPORT Enable support for MMC cards config MMCSD_HAVECARDDETECT - bool "MMC/SD card detection" - default y - ---help--- - SDIO driver card detection is - 100% accurate + bool "MMC/SD card detection" + default y + ---help--- + SDIO driver card detection is + 100% accurate + +config MMCSD_HAVE_SDIOWAIT_WRCOMPLETE + bool "Use SDIO_D Busy to detect Write Complete" + default n + ---help--- + SDIO driver will use SDIO_D Busy signaling to detect Write Complete. + This option when selected, will enable the MMCSD driver to use the + underlying (stm32_sdio only) drivers implementation of the SD specs + SDIO_D Busy signaling to detect Write Complete. This will avoid + potentially very long (600Ms+) busy waiting in the MMCSD driver. + To implement SDIO_D Busy signaling, the underlying driver must + be capable of switching the GPIO_SDIO_D0 to be a rising edge sensitive + interrupt pin. It must then, condition that pin to detect the rising edge + on recipet of SDWAIT_WRCOMPLETE in the SDIO_WAITENABLE call and + return it back to regular SDIO mode, when either the ISR fires or pin is + found to be high in the SDIO_EVENTWAIT call. config MMCSD_SPI bool "MMC/SD SPI transfer support" diff --git a/nuttx/drivers/mmcsd/mmcsd_sdio.c b/nuttx/drivers/mmcsd/mmcsd_sdio.c index e208a8aca..d036cba84 100644..100755 --- a/nuttx/drivers/mmcsd/mmcsd_sdio.c +++ b/nuttx/drivers/mmcsd/mmcsd_sdio.c @@ -1150,6 +1150,15 @@ static int mmcsd_transferready(FAR struct mmcsd_state_s *priv) * the TRANSFER state when the card completes the WRITE operation. */ +#if defined(CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE) + ret = mmcsd_eventwait(priv, SDIOWAIT_TIMEOUT|SDIOWAIT_ERROR, MMCSD_BLOCK_WDATADELAY); + + if (ret != OK) + { + fdbg("ERROR: mmcsd_eventwait for transferready failed: %d\n", ret); + } +#endif + starttime = clock_systimer(); do { @@ -1721,6 +1730,14 @@ static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, return ret; } +#if defined(CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE) + + /* Arm the write complete detection with timeout */ + + SDIO_WAITENABLE(priv->dev, SDIOWAIT_WRCOMPLETE|SDIOWAIT_TIMEOUT); + +#endif + /* On success, return the number of blocks written */ return 1; diff --git a/nuttx/include/nuttx/sdio.h b/nuttx/include/nuttx/sdio.h index 5bd80329c..772bf99d1 100644..100755 --- a/nuttx/include/nuttx/sdio.h +++ b/nuttx/include/nuttx/sdio.h @@ -62,9 +62,12 @@ #define SDIOWAIT_TRANSFERDONE (1 << 2) /* Bit 2: Data transfer/DMA done */ #define SDIOWAIT_TIMEOUT (1 << 3) /* Bit 3: Timeout */ #define SDIOWAIT_ERROR (1 << 4) /* Bit 4: Some other error occurred */ - -#define SDIOWAIT_ALLEVENTS 0x1f - +#if defined(CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE) +#define SDIOWAIT_WRCOMPLETE (1 << 5) /* Bit 5: Hardware Write Completion */ +# define SDIOWAIT_ALLEVENTS 0x3f +#else +# define SDIOWAIT_ALLEVENTS 0x1f +#endif /* Media events are used for enable/disable registered event callbacks */ #define SDIOMEDIA_EJECTED (1 << 0) /* Bit 0: Mmedia removed */ |