summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/lpc17xx
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-03-05 14:46:04 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-03-05 14:46:04 +0000
commit2f6ff23170be952702278336d624b1cb88651e84 (patch)
tree732e98804a6178d18323c3e102f241d27845ba9f /nuttx/arch/arm/src/lpc17xx
parent8519cad9b7e4d81618d367bea59fb82ded5a07dc (diff)
downloadpx4-nuttx-2f6ff23170be952702278336d624b1cb88651e84.tar.gz
px4-nuttx-2f6ff23170be952702278336d624b1cb88651e84.tar.bz2
px4-nuttx-2f6ff23170be952702278336d624b1cb88651e84.zip
Open1788 uses SDIO-based SD card (not SPI); clone STM32 SDIO interface to LPC17xx
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5708 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/arm/src/lpc17xx')
-rw-r--r--nuttx/arch/arm/src/lpc17xx/Kconfig49
-rw-r--r--nuttx/arch/arm/src/lpc17xx/chip/lpc17_sdcard.h244
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_sdcard.c2800
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_sdcard.h127
4 files changed, 3220 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/lpc17xx/Kconfig b/nuttx/arch/arm/src/lpc17xx/Kconfig
index 3d4c8b4e5..81ca87f04 100644
--- a/nuttx/arch/arm/src/lpc17xx/Kconfig
+++ b/nuttx/arch/arm/src/lpc17xx/Kconfig
@@ -61,6 +61,7 @@ config ARCH_CHIP_LPC1769
config ARCH_CHIP_LPC1773
bool "LPC1773"
select ARCH_FAMILY_LPC177X
+ select ARCH_HAVE_SPIFI
config ARCH_CHIP_LPC1774
bool "LPC1774"
@@ -108,6 +109,7 @@ config ARCH_FAMILY_LPC177X
select ARCH_HAVE_EXTSRAM0
select ARCH_HAVE_EXTDRAM
select ARCH_HAVE_EXTNOR
+ select ARCH_HAVE_SDIO
config ARCH_FAMILY_LPC178X
bool
@@ -115,6 +117,13 @@ config ARCH_FAMILY_LPC178X
select ARCH_HAVE_EXTSRAM0
select ARCH_HAVE_EXTDRAM
select ARCH_HAVE_EXTNOR
+ select ARCH_HAVE_SDIO
+
+config ARCH_HAVE_SPIFI
+ bool
+
+config ARCH_HAVE_SDIO
+ bool
menu "LPC17xx Peripheral Support"
@@ -156,6 +165,11 @@ config LPC17_USBOTG
default n
depends on LPC17_USBHOST && LPC17_USBDEV
+config LPC17_SDCARD
+ bool "SD Card Interface"
+ depends on ARCH_HAVE_SDIO
+ default n
+
config LPC17_UART0
bool "UART0"
select ARCH_HAVE_UART0
@@ -197,6 +211,11 @@ config LPC17_SSP1
bool "SSP1"
default n
+config LPC17_SPIFI
+ bool "SPIFI Interface"
+ depends on ARCH_HAVE_SPIFI
+ default n
+
config LPC17_I2C0
bool "I2C0"
default n
@@ -437,6 +456,36 @@ config I2C2_FREQ
endmenu
+menu "SDIO Configuration"
+ depends on LPC17_SDCARD
+
+config SDIO_DMA
+ bool "Support DMA data transfers"
+ default y if LPC17_GPDMA
+ depends on LPC17_GPDMA
+ ---help---
+ Support DMA data transfers.
+ Enable SD card DMA data transfers. This is a marginally optional.
+ For most usages, SD accesses will cause data overruns if used without
+ DMA. Requires LPC17_SDCARD and config LPC17_GPDMA.
+
+config SDIO_DMAPRIO
+ hex "SDIO DMA priority"
+ default 0x0
+ depends on LPC17_GPDMA
+ ---help---
+ Select SDIO DMA prority.
+
+config SDIO_WIDTH_D1_ONLY
+ bool "Use D1 only"
+ default n
+ ---help---
+ Select 1-bit transfer mode. 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).Default: 4-bit transfer mode.
+
+endmenu
+
menu "Ethernet driver options"
config PHY_AUTONEG
diff --git a/nuttx/arch/arm/src/lpc17xx/chip/lpc17_sdcard.h b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_sdcard.h
new file mode 100644
index 000000000..ed9296706
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc17xx/chip/lpc17_sdcard.h
@@ -0,0 +1,244 @@
+/************************************************************************************
+ * arch/arm/src/lpc17xx/chip/lpc17_sdcard.h
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_LPC17XX_CHIP_LPC17_SDCARD_H
+#define __ARCH_ARM_SRC_LPC17XX_CHIP_LPC17_SDCARD_H
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* Register Offsets *****************************************************************/
+
+#define LPC17_SDCARD_PWR_OFFSET 0x0000 /* SD card power control register */
+#define LPC17_SDCARD_CLOCK_OFFSET 0x0004 /* SD card clock control register */
+#define LPC17_SDCARD_ARG_OFFSET 0x0008 /* SD card argument register */
+#define LPC17_SDCARD_CMD_OFFSET 0x000c /* SD card command register */
+#define LPC17_SDCARD_RESPCMD_OFFSET 0x0010 /* SD card command response register */
+#define LPC17_SDCARD_RESP_OFFSET(n) (0x0010+4*(n))
+#define LPC17_SDCARD_RESP0_OFFSET 0x0014 /* SD card response 1 register */
+#define LPC17_SDCARD_RESP1_OFFSET 0x0018 /* SD card response 2 register */
+#define LPC17_SDCARD_RESP2_OFFSET 0x001c /* SD card response 3 register */
+#define LPC17_SDCARD_RESP3_OFFSET 0x0020 /* SD card response 4 register */
+#define LPC17_SDCARD_DTIMER_OFFSET 0x0024 /* SD card data timer register */
+#define LPC17_SDCARD_DLEN_OFFSET 0x0028 /* SD card data length register */
+#define LPC17_SDCARD_DCTRL_OFFSET 0x002c /* SD card data control register */
+#define LPC17_SDCARD_DCOUNT_OFFSET 0x0030 /* SD card data counter register */
+#define LPC17_SDCARD_STATUS_OFFSET 0x0034 /* SD card status register */
+#define LPC17_SDCARD_CLEAR_OFFSET 0x0038 /* SD card interrupt clear register */
+#define LPC17_SDCARD_MASK0_OFFSET 0x003c /* SD card mask register */
+#define LPC17_SDCARD_FIFOCNT_OFFSET 0x0048 /* SD card FIFO counter register */
+#define LPC17_SDCARD_FIFO_OFFSET 0x0080 /* SD card data FIFO register */
+
+/* Register Addresses ***************************************************************/
+
+#define LPC17_SDCARD_PWR (LPC17_SDCARD_BASE+LPC17_SDCARD_PWR_OFFSET)
+#define LPC17_SDCARD_CLOCK (LPC17_SDCARD_BASE+LPC17_SDCARD_CLOCK_OFFSET)
+#define LPC17_SDCARD_ARG (LPC17_SDCARD_BASE+LPC17_SDCARD_ARG_OFFSET)
+#define LPC17_SDCARD_CMD (LPC17_SDCARD_BASE+LPC17_SDCARD_CMD_OFFSET)
+#define LPC17_SDCARD_RESPCMD (LPC17_SDCARD_BASE+LPC17_SDCARD_RESPCMD_OFFSET)
+#define LPC17_SDCARD_RESP(n) (LPC17_SDCARD_BASE+LPC17_SDCARD_RESP_OFFSET(n))
+#define LPC17_SDCARD_RESP0 (LPC17_SDCARD_BASE+LPC17_SDCARD_RESP0_OFFSET)
+#define LPC17_SDCARD_RESP1 (LPC17_SDCARD_BASE+LPC17_SDCARD_RESP1_OFFSET)
+#define LPC17_SDCARD_RESP2 (LPC17_SDCARD_BASE+LPC17_SDCARD_RESP2_OFFSET)
+#define LPC17_SDCARD_RESP3 (LPC17_SDCARD_BASE+LPC17_SDCARD_RESP3_OFFSET)
+#define LPC17_SDCARD_DTIMER (LPC17_SDCARD_BASE+LPC17_SDCARD_DTIMER_OFFSET)
+#define LPC17_SDCARD_DLEN (LPC17_SDCARD_BASE+LPC17_SDCARD_DLEN_OFFSET)
+#define LPC17_SDCARD_DCTRL (LPC17_SDCARD_BASE+LPC17_SDCARD_DCTRL_OFFSET)
+#define LPC17_SDCARD_DCOUNT (LPC17_SDCARD_BASE+LPC17_SDCARD_DCOUNT_OFFSET)
+#define LPC17_SDCARD_STATUS (LPC17_SDCARD_BASE+LPC17_SDCARD_STATUS_OFFSET)
+#define LPC17_SDCARD_CLEAR (LPC17_SDCARD_BASE+LPC17_SDCARD_CLEAR_OFFSET)
+#define LPC17_SDCARD_MASK0 (LPC17_SDCARD_BASE+LPC17_SDCARD_MASK0_OFFSET)
+#define LPC17_SDCARD_FIFOCNT (LPC17_SDCARD_BASE+LPC17_SDCARD_FIFOCNT_OFFSET)
+#define LPC17_SDCARD_FIFO (LPC17_SDCARD_BASE+LPC17_SDCARD_FIFO_OFFSET)
+
+/* Register Bitfield Definitions ****************************************************/
+
+#define SDCARD_PWR_CTRL_SHIFT (0) /* Bits 0-1: Power supply control bits */
+#define SDCARD_PWR_CTRL_MASK (3 << SDCARD_PWR_CTRL_SHIFT)
+# define SDCARD_PWR_CTRL_OFF (0 << SDCARD_PWR_CTRL_SHIFT) /* 00: Power-off: card clock stopped */
+# define SDCARD_PWR_CTRL_PWRUP (2 << SDCARD_PWR_CTRL_SHIFT) /* 10: Reserved power-up */
+# define SDCARD_PWR_CTRL_ON (3 << SDCARD_PWR_CTRL_SHIFT) /* 11: Power-on: card is clocked */
+
+#define SDCARD_PWR_RESET (0) /* Reset value */
+
+#define SDCARD_CLOCK_CLKDIV_SHIFT (0) /* Bits 7-0: Clock divide factor */
+#define SDCARD_CLOCK_CLKDIV_MASK (0xff << SDCARD_CLOCK_CLKDIV_SHIFT)
+#define SDCARD_CLOCK_CLKEN (1 << 8) /* Bit 8: Clock enable bit */
+#define SDCARD_CLOCK_PWRSAV (1 << 9) /* Bit 9: Power saving configuration bit */
+#define SDCARD_CLOCK_BYPASS (1 << 10) /* Bit 10: Clock divider bypass enable bit */
+#define SDCARD_CLOCK_WIDBUS_SHIFT (11) /* Bits 12-11: Wide bus mode enable bits */
+#define SDCARD_CLOCK_WIDBUS_MASK (3 << SDCARD_CLOCK_WIDBUS_SHIFT)
+# define SDCARD_CLOCK_WIDBUS_D1 (0 << SDCARD_CLOCK_WIDBUS_SHIFT) /* 00: Default (SDIO_D0) */
+# define SDCARD_CLOCK_WIDBUS_D4 (1 << SDCARD_CLOCK_WIDBUS_SHIFT) /* 01: 4-wide (SDIO_D[3:0]) */
+# define SDCARD_CLOCK_WIDBUS_D8 (2 << SDCARD_CLOCK_WIDBUS_SHIFT) /* 10: 8-wide (SDIO_D[7:0]) */
+#define SDCARD_CLOCK_NEGEDGE (1 << 13) /* Bit 13: SDIO_CK dephasing selection bit */
+#define SDCARD_CLOCK_HWFC_EN (1 << 14) /* Bit 14: HW Flow Control enable */
+
+#define SDCARD_CLOCK_RESET (0) /* Reset value */
+#define SDCARD_ARG_RESET (0) /* Reset value */
+
+#define SDCARD_CMD_INDEX_SHIFT (0)
+#define SDCARD_CMD_INDEX_MASK (0x3f << SDCARD_CMD_INDEX_SHIFT)
+#define SDCARD_CMD_WAITRESP_SHIFT (6) /* Bits 7-6: Wait for response bits */
+#define SDCARD_CMD_WAITRESP_MASK (3 << SDCARD_CMD_WAITRESP_SHIFT)
+# define SDCARD_CMD_NORESPONSE (0 << SDCARD_CMD_WAITRESP_SHIFT) /* 00/10: No response */
+# define SDCARD_CMD_SHORTRESPONSE (1 << SDCARD_CMD_WAITRESP_SHIFT) /* 01: Short response */
+# define SDCARD_CMD_LONGRESPONSE (3 << SDCARD_CMD_WAITRESP_SHIFT) /* 11: Long response */
+#define SDCARD_CMD_WAITINT (1 << 8) /* Bit 8: CPSM waits for interrupt request */
+#define SDCARD_CMD_WAITPEND (1 << 9) /* Bit 9: CPSM Waits for ends of data transfer */
+#define SDCARD_CMD_CPSMEN (1 << 10) /* Bit 10: Command path state machine enable */
+#define SDCARD_CMD_SUSPEND (1 << 11) /* Bit 11: SD I/O suspend command */
+#define SDCARD_CMD_ENDCMD (1 << 12) /* Bit 12: Enable CMD completion */
+#define SDCARD_CMD_NIEN (1 << 13) /* Bit 13: not Interrupt Enable */
+#define SDCARD_CMD_ATACMD (1 << 14) /* Bit 14: CE-ATA command */
+
+#define SDCARD_CMD_RESET (0) /* Reset value */
+
+#define SDCARD_RESPCMD_SHIFT (0)
+#define SDCARD_RESPCMD_MASK (0x3f << SDCARD_RESPCMD_SHIFT)
+
+#define SDCARD_DTIMER_RESET (0) /* Reset value */
+
+#define SDCARD_DLEN_SHIFT (0)
+#define SDCARD_DLEN_MASK (0x01ffffff << SDCARD_DLEN_SHIFT)
+
+#define SDCARD_DLEN_RESET (0) /* Reset value */
+
+#define SDCARD_DCTRL_DTEN (1 << 0) /* Bit 0: Data transfer enabled bit */
+#define SDCARD_DCTRL_DTDIR (1 << 1) /* Bit 1: Data transfer direction */
+#define SDCARD_DCTRL_DTMODE (1 << 2) /* Bit 2: Data transfer mode */
+#define SDCARD_DCTRL_DMAEN (1 << 3) /* Bit 3: DMA enable bit */
+#define SDCARD_DCTRL_DBLOCKSIZE_SHIFT (4) /* Bits 7-4: Data block size */
+#define SDCARD_DCTRL_DBLOCKSIZE_MASK (15 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_1BYTE (0 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_2BYTES (1 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_4BYTES (2 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_8BYTES (3 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_16BYTES (4 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_32BYTES (5 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_64BYTES (6 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_128BYTES (7 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_256BYTES (8 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_512BYTES (9 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_1KBYTE (10 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_2KBYTES (11 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_4KBYTES (12 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_8KBYTES (13 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+# define SDCARD_DCTRL_16KBYTES (14 << SDCARD_DCTRL_DBLOCKSIZE_SHIFT)
+#define SDCARD_DCTRL_RWSTART (1 << 8) /* Bit 8: Read wait start */
+#define SDCARD_DCTRL_RWSTOP (1 << 9) /* Bit 9: Read wait stop */
+#define SDCARD_DCTRL_RWMOD (1 << 10) /* Bit 10: Read wait mode */
+#define SDCARD_DCTRL_SDIOEN (1 << 11) /* Bit 11: SD I/O enable functions */
+
+#define SDCARD_DCTRL_RESET (0) /* Reset value */
+
+#define SDCARD_DATACOUNT_SHIFT (0)
+#define SDCARD_DATACOUNT_MASK (0x01ffffff << SDCARD_DATACOUNT_SHIFT)
+
+#define SDCARD_STATUS_CCRCFAIL (1 << 0) /* Bit 0: Command response CRC fail */
+#define SDCARD_STATUS_DCRCFAIL (1 << 1) /* Bit 1: Data block CRC fail */
+#define SDCARD_STATUS_CTIMEOUT (1 << 2) /* Bit 2: Command response timeout */
+#define SDCARD_STATUS_DTIMEOUT (1 << 3) /* Bit 3: Data timeout */
+#define SDCARD_STATUS_TXUNDERR (1 << 4) /* Bit 4: Transmit FIFO underrun error */
+#define SDCARD_STATUS_RXOVERR (1 << 5) /* Bit 5: Received FIFO overrun error */
+#define SDCARD_STATUS_CMDREND (1 << 6) /* Bit 6: Command response received */
+#define SDCARD_STATUS_CMDSENT (1 << 7) /* Bit 7: Command sent */
+#define SDCARD_STATUS_DATAEND (1 << 8) /* Bit 8: Data end */
+#define SDCARD_STATUS_STBITERR (1 << 9) /* Bit 9: Start bit not detected */
+#define SDCARD_STATUS_DBCKEND (1 << 10) /* Bit 10: Data block sent/received */
+#define SDCARD_STATUS_CMDACT (1 << 11) /* Bit 11: Command transfer in progress */
+#define SDCARD_STATUS_TXACT (1 << 12) /* Bit 12: Data transmit in progress */
+#define SDCARD_STATUS_RXACT (1 << 13) /* Bit 13: Data receive in progress */
+#define SDCARD_STATUS_TXFIFOHE (1 << 14) /* Bit 14: Transmit FIFO half empty */
+#define SDCARD_STATUS_RXFIFOHF (1 << 15) /* Bit 15: Receive FIFO half full */
+#define SDCARD_STATUS_TXFIFOF (1 << 16) /* Bit 16: Transmit FIFO full */
+#define SDCARD_STATUS_RXFIFOF (1 << 17) /* Bit 17: Receive FIFO full */
+#define SDCARD_STATUS_TXFIFOE (1 << 18) /* Bit 18: Transmit FIFO empty */
+#define SDCARD_STATUS_RXFIFOE (1 << 19) /* Bit 19: Receive FIFO empty */
+#define SDCARD_STATUS_TXDAVL (1 << 20) /* Bit 20: Data available in transmit FIFO */
+#define SDCARD_STATUS_RXDAVL (1 << 21) /* Bit 21: Data available in receive FIFO */
+#define SDCARD_STATUS_SDIOIT (1 << 22) /* Bit 22: SDIO interrupt received */
+#define SDCARD_STATUS_CEATAEND (1 << 23) /* Bit 23: CMD6 CE-ATA command completion */
+
+#define SDCARD_CLEAR_CCRCFAILC (1 << 0) /* Bit 0: CCRCFAIL flag clear bit */
+#define SDCARD_CLEAR_DCRCFAILC (1 << 1) /* Bit 1: DCRCFAIL flag clear bit */
+#define SDCARD_CLEAR_CTIMEOUTC (1 << 2) /* Bit 2: CTIMEOUT flag clear bit */
+#define SDCARD_CLEAR_DTIMEOUTC (1 << 3) /* Bit 3: DTIMEOUT flag clear bit */
+#define SDCARD_CLEAR_TXUNDERRC (1 << 4) /* Bit 4: TXUNDERR flag clear bit */
+#define SDCARD_CLEAR_RXOVERRC (1 << 5) /* Bit 5: RXOVERR flag clear bit */
+#define SDCARD_CLEAR_CMDRENDC (1 << 6) /* Bit 6: CMDREND flag clear bit */
+#define SDCARD_CLEAR_CMDSENTC (1 << 7) /* Bit 7: CMDSENT flag clear bit */
+#define SDCARD_CLEAR_DATAENDC (1 << 8) /* Bit 8: DATAEND flag clear bit */
+#define SDCARD_CLEAR_STBITERRC (1 << 9) /* Bit 9: STBITERR flag clear bit */
+#define SDCARD_CLEAR_DBCKENDC (1 << 10) /* Bit 10: DBCKEND flag clear bit */
+#define SDCARD_CLEAR_SDIOITC (1 << 22) /* Bit 22: SDIOIT flag clear bit */
+#define SDCARD_CLEAR_CEATAENDC (1 << 23) /* Bit 23: CEATAEND flag clear bit */
+
+#define SDCARD_CLEAR_RESET 0x00c007ff
+#define SDCARD_CLEAR_STATICFLAGS 0x000005ff
+
+#define SDCARD_MASK_CCRCFAILIE (1 << 0) /* Bit 0: Command CRC fail interrupt enable */
+#define SDCARD_MASK_DCRCFAILIE (1 << 1) /* Bit 1: Data CRC fail interrupt enable */
+#define SDCARD_MASK_CTIMEOUTIE (1 << 2) /* Bit 2: Command timeout interrupt enable */
+#define SDCARD_MASK_DTIMEOUTIE (1 << 3) /* Bit 3: Data timeout interrupt enable */
+#define SDCARD_MASK_TXUNDERRIE (1 << 4) /* Bit 4: Tx FIFO underrun error interrupt enable */
+#define SDCARD_MASK_RXOVERRIE (1 << 5) /* Bit 5: Rx FIFO overrun error interrupt enable */
+#define SDCARD_MASK_CMDRENDIE (1 << 6) /* Bit 6: Command response received interrupt enable */
+#define SDCARD_MASK_CMDSENTIE (1 << 7) /* Bit 7: Command sent interrupt enable */
+#define SDCARD_MASK_DATAENDIE (1 << 8) /* Bit 8: Data end interrupt enable */
+#define SDCARD_MASK_STBITERRIE (1 << 9) /* Bit 9: Start bit error interrupt enable */
+#define SDCARD_MASK_DBCKENDIE (1 << 10) /* Bit 10: Data block end interrupt enable */
+#define SDCARD_MASK_CMDACTIE (1 << 11) /* Bit 11: Command acting interrupt enable */
+#define SDCARD_MASK_TXACTIE (1 << 12) /* Bit 12: Data transmit acting interrupt enable */
+#define SDCARD_MASK_RXACTIE (1 << 13) /* Bit 13: Data receive acting interrupt enable */
+#define SDCARD_MASK_TXFIFOHEIE (1 << 14) /* Bit 14: Tx FIFO half empty interrupt enable */
+#define SDCARD_MASK_RXFIFOHFIE (1 << 15) /* Bit 15: Rx FIFO half full interrupt enable */
+#define SDCARD_MASK_TXFIFOFIE (1 << 16) /* Bit 16: Tx FIFO full interrupt enable */
+#define SDCARD_MASK_RXFIFOFIE (1 << 17) /* Bit 17: Rx FIFO full interrupt enable */
+#define SDCARD_MASK_TXFIFOEIE (1 << 18) /* Bit 18: Tx FIFO empty interrupt enable */
+#define SDCARD_MASK_RXFIFOEIE (1 << 19) /* Bit 19: Rx FIFO empty interrupt enable */
+#define SDCARD_MASK_TXDAVLIE (1 << 20) /* Bit 20: Data available in Tx FIFO interrupt enable */
+#define SDCARD_MASK_RXDAVLIE (1 << 21) /* Bit 21: Data available in Rx FIFO interrupt enable */
+#define SDCARD_MASK_SDIOITIE (1 << 22) /* Bit 22: SDIO mode interrupt received interrupt enable */
+#define SDCARD_MASK_CEATAENDIE (1 << 23) /* Bit 23: CE-ATA command completion interrupt enable */
+
+#define SDCARD_MASK_RESET (0)
+
+#define SDCARD_FIFOCNT_SHIFT (0)
+#define SDCARD_FIFOCNT_MASK (0x01ffffff << SDCARD_FIFOCNT_SHIFT)
+
+#endif /* __ARCH_ARM_SRC_LPC17XX_CHIP_LPC17_SDCARD_H */
+
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_sdcard.c b/nuttx/arch/arm/src/lpc17xx/lpc17_sdcard.c
new file mode 100644
index 000000000..7abdbad1c
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_sdcard.c
@@ -0,0 +1,2800 @@
+/****************************************************************************
+ * arch/arm/src/lpc17xx/lpc17_sdcard.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <string.h>
+#include <assert.h>
+#include <debug.h>
+#include <wdog.h>
+#include <errno.h>
+
+#include <nuttx/clock.h>
+#include <nuttx/arch.h>
+#include <nuttx/sdio.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/mmcsd.h>
+
+#include <arch/irq.h>
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "up_arch.h"
+
+#include "lpc17_dma.h"
+#include "lpc17_sdcard.h"
+
+#if CONFIG_LPC17_SDCARD
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+/* Required system configuration options:
+ *
+ * CONFIG_ARCH_DMA - Enable architecture-specific DMA subsystem
+ * initialization. Required if CONFIG_SDIO_DMA is enabled.
+ * CONFIG_LPC17_GPDMA - Enable LPC17XX DMA2 support. Required if
+ * CONFIG_SDIO_DMA is enabled
+ * CONFIG_SCHED_WORKQUEUE -- Callback support requires work queue support.
+ *
+ * Driver-specific configuration options:
+ *
+ * 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_SDIO_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_SDIO_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).
+ * CONFIG_SDCARD_DMAPRIO - SD card DMA priority. This can be selected if
+ * CONFIG_SDIO_DMA is enabled.
+ * CONFIG_DEBUG_SDIO - Enables some very low-level debug output
+ * This also requires CONFIG_DEBUG_FS and CONFIG_DEBUG_VERBOSE
+ */
+
+#if defined(CONFIG_SDIO_DMA) && !defined(CONFIG_LPC17_GPDMA)
+# warning "CONFIG_SDIO_DMA support requires CONFIG_LPC17_GPDMA"
+#endif
+
+#ifndef CONFIG_SDIO_DMA
+# warning "Large Non-DMA transfer may result in RX overrun failures"
+#endif
+
+#ifndef CONFIG_SCHED_WORKQUEUE
+# error "Callback support requires CONFIG_SCHED_WORKQUEUE"
+#endif
+
+#ifdef CONFIG_SDIO_DMA
+# define CONFIG_SDCARD_DMAPRIO DMA_SCR_PRIVERYHI
+# if (CONFIG_SDCARD_DMAPRIO & ~DMA_SCR_PL_MASK) != 0
+# error "Illegal value for CONFIG_SDCARD_DMAPRIO"
+# endif
+#endif
+
+#if !defined(CONFIG_DEBUG_FS) || !defined(CONFIG_DEBUG)
+# undef CONFIG_DEBUG_SDIO
+#endif
+
+/* Friendly CLKCR bit re-definitions ****************************************/
+
+#define SDCARD_CLOCK_RISINGEDGE (0)
+#define SDCARD_CLOCK_FALLINGEDGE SDCARD_CLOCK_NEGEDGE
+
+/* Mode dependent settings. These depend on clock devisor settings that must
+ * be defined in the board-specific board.h header file: SDCARD_INIT_CLKDIV,
+ * SDCARD_MMCXFR_CLKDIV, and SDCARD_SDXFR_CLKDIV.
+ */
+
+#define LPC17_CLCKCR_INIT (SDCARD_INIT_CLKDIV|SDCARD_CLOCK_RISINGEDGE|\
+ SDCARD_CLOCK_WIDBUS_D1)
+#define SDCARD_CLOCK_MMCXFR (SDCARD_MMCXFR_CLKDIV|SDCARD_CLOCK_RISINGEDGE|\
+ SDCARD_CLOCK_WIDBUS_D1)
+#define SDCARD_CLOCK_SDXFR (SDCARD_SDXFR_CLKDIV|SDCARD_CLOCK_RISINGEDGE|\
+ SDCARD_CLOCK_WIDBUS_D1)
+#define SDCARD_CLOCK_SDWIDEXFR (SDCARD_SDXFR_CLKDIV|SDCARD_CLOCK_RISINGEDGE|\
+ SDCARD_CLOCK_WIDBUS_D4)
+/* Timing */
+
+#define SDCARD_CMDTIMEOUT (100000)
+#define SDCARD_LONGTIMEOUT (0x7fffffff)
+
+/* Big DTIMER setting */
+
+#define SDCARD_DTIMER_DATATIMEOUT (0x000fffff)
+
+/* DMA channel/stream configuration register settings. The following
+ * must be selected. The DMA driver will select the remaining fields.
+ *
+ * - 32-bit DMA
+ * - Memory increment
+ * - Direction (memory-to-peripheral, peripheral-to-memory)
+ * - Memory burst size (F4 only)
+ */
+
+/* Stream configuration register (SCR) settings. */
+
+#define SDCARD_RXDMA32_CONFIG (DMA_SCR_PFCTRL|DMA_SCR_DIR_P2M|DMA_SCR_MINC|\
+ DMA_SCR_PSIZE_32BITS|DMA_SCR_MSIZE_32BITS|\
+ CONFIG_SDCARD_DMAPRIO|DMA_SCR_PBURST_INCR4|\
+ DMA_SCR_MBURST_INCR4)
+#define SDCARD_TXDMA32_CONFIG (DMA_SCR_PFCTRL|DMA_SCR_DIR_M2P|DMA_SCR_MINC|\
+ DMA_SCR_PSIZE_32BITS|DMA_SCR_MSIZE_32BITS|\
+ CONFIG_SDCARD_DMAPRIO|DMA_SCR_PBURST_INCR4|\
+ DMA_SCR_MBURST_INCR4)
+
+/* SD card DMA Channel/Stream selection. For the the case of the LPC17XX F4, there
+ * are multiple DMA stream options that must be dis-ambiguated in the board.h
+ * file.
+ */
+
+#define SDCARD_DMACHAN DMAMAP_SDCARD
+
+/* FIFO sizes */
+
+#define SDCARD_HALFFIFO_WORDS (8)
+#define SDCARD_HALFFIFO_BYTES (8*4)
+
+/* Data transfer interrupt mask bits */
+
+#define SDCARD_RECV_MASK (SDCARD_MASK0_DCRCFAILIE|SDCARD_MASK0_DTIMEOUTIE|\
+ SDCARD_MASK0_DATAENDIE|SDCARD_MASK0_RXOVERRIE|\
+ SDCARD_MASK0_RXFIFOHFIE|SDCARD_MASK0_STBITERRIE)
+#define SDCARD_SEND_MASK (SDCARD_MASK0_DCRCFAILIE|SDCARD_MASK0_DTIMEOUTIE|\
+ SDCARD_MASK0_DATAENDIE|SDCARD_MASK0_TXUNDERRIE|\
+ SDCARD_MASK0_TXFIFOHEIE|SDCARD_MASK0_STBITERRIE)
+#define SDCARD_DMARECV_MASK (SDCARD_MASK0_DCRCFAILIE|SDCARD_MASK0_DTIMEOUTIE|\
+ SDCARD_MASK0_DATAENDIE|SDCARD_MASK0_RXOVERRIE|\
+ SDCARD_MASK0_STBITERRIE)
+#define SDCARD_DMASEND_MASK (SDCARD_MASK0_DCRCFAILIE|SDCARD_MASK0_DTIMEOUTIE|\
+ SDCARD_MASK0_DATAENDIE|SDCARD_MASK0_TXUNDERRIE|\
+ SDCARD_MASK0_STBITERRIE)
+
+/* Event waiting interrupt mask bits */
+
+#define SDCARD_CMDDONE_STA (SDCARD_STATUS_CMDSENT)
+#define SDCARD_RESPDONE_STA (SDCARD_STATUS_CTIMEOUT|SDCARD_STATUS_CCRCFAIL|\
+ SDCARD_STATUS_CMDREND)
+#define SDCARD_XFRDONE_STA (0)
+
+#define SDCARD_CMDDONE_MASK (SDCARD_MASK0_CMDSENTIE)
+#define SDCARD_RESPDONE_MASK (SDCARD_MASK0_CCRCFAILIE|SDCARD_MASK0_CTIMEOUTIE|\
+ SDCARD_MASK0_CMDRENDIE)
+#define SDCARD_XFRDONE_MASK (0)
+
+#define SDCARD_CMDDONE_ICR (SDCARD_CLEAR_CMDSENTC)
+#define SDCARD_RESPDONE_ICR (SDCARD_CLEAR_CTIMEOUTC|SDCARD_CLEAR_CCRCFAILC|\
+ SDCARD_CLEAR_CMDRENDC)
+#define SDCARD_XFRDONE_ICR (SDCARD_CLEAR_DATAENDC|SDCARD_CLEAR_DCRCFAILC|\
+ SDCARD_CLEAR_DTIMEOUTC|SDCARD_CLEAR_RXOVERRC|\
+ SDCARD_CLEAR_TXUNDERRC|SDCARD_CLEAR_STBITERRC)
+
+#define SDCARD_WAITALL_ICR (SDCARD_CMDDONE_ICR|SDCARD_RESPDONE_ICR|\
+ SDCARD_XFRDONE_ICR)
+
+/* Let's wait until we have both SD card transfer complete and DMA complete. */
+
+#define SDCARD_XFRDONE_FLAG (1)
+#define SDCARD_DMADONE_FLAG (2)
+#define SDCARD_ALLDONE (3)
+
+/* Register logging support */
+
+#ifdef CONFIG_DEBUG_SDIO
+# ifdef CONFIG_SDIO_DMA
+# define SAMPLENDX_BEFORE_SETUP 0
+# define SAMPLENDX_BEFORE_ENABLE 1
+# define SAMPLENDX_AFTER_SETUP 2
+# define SAMPLENDX_END_TRANSFER 3
+# define SAMPLENDX_DMA_CALLBACK 4
+# define DEBUG_NSAMPLES 5
+# else
+# define SAMPLENDX_BEFORE_SETUP 0
+# define SAMPLENDX_AFTER_SETUP 1
+# define SAMPLENDX_END_TRANSFER 2
+# define DEBUG_NSAMPLES 3
+# endif
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure defines the state of the LPC17XX SD card interface */
+
+struct lpc17_dev_s
+{
+ struct sdio_dev_s dev; /* Standard, base SD card interface */
+
+ /* LPC17XX-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 */
+ volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */
+ WDOG_ID waitwdog; /* Watchdog that handles event timeouts */
+
+ /* Callback support */
+
+ uint8_t cdstatus; /* Card status */
+ sdio_eventset_t cbevents; /* Set of events to be cause callbacks */
+ worker_t callback; /* Registered callback function */
+ void *cbarg; /* Registered callback argument */
+ struct work_s cbwork; /* Callback work queue structure */
+
+ /* Interrupt mode data transfer support */
+
+ uint32_t *buffer; /* Address of current R/W buffer */
+ size_t remaining; /* Number of bytes remaining in the transfer */
+ uint32_t xfrmask; /* Interrupt enables for data transfer */
+
+ /* DMA data transfer support */
+
+ bool widebus; /* Required for DMA support */
+#ifdef CONFIG_SDIO_DMA
+ volatile uint8_t xfrflags; /* Used to synchronize SD card and DMA completion events */
+ bool dmamode; /* true: DMA mode transfer */
+ DMA_HANDLE dma; /* Handle for DMA channel */
+#endif
+};
+
+/* Register logging support */
+
+#ifdef CONFIG_DEBUG_SDIO
+struct lpc17_sdcard_regs_s
+{
+ uint8_t pwr;
+ uint16_t clkcr;
+ uint16_t dctrl;
+ uint32_t dtimer;
+ uint32_t dlen;
+ uint32_t dcount;
+ uint32_t sta;
+ uint32_t mask;
+ uint32_t fifocnt;
+};
+
+struct lpc17_sampleregs_s
+{
+ struct lpc17_sdcard_regs_s sdcard;
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ struct lpc17_dmaregs_s dma;
+#endif
+};
+#endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Low-level helpers ********************************************************/
+
+static void lpc17_takesem(struct lpc17_dev_s *priv);
+#define lpc17_givesem(priv) (sem_post(&priv->waitsem))
+static inline void lpc17_setclock(uint32_t clkcr);
+static void lpc17_configwaitints(struct lpc17_dev_s *priv, uint32_t waitmask,
+ sdio_eventset_t waitevents, sdio_eventset_t wkupevents);
+static void lpc17_configxfrints(struct lpc17_dev_s *priv, uint32_t xfrmask);
+static void lpc17_setpwrctrl(uint32_t pwrctrl);
+static inline uint32_t lpc17_getpwrctrl(void);
+
+/* DMA Helpers **************************************************************/
+
+#ifdef CONFIG_DEBUG_SDIO
+static void lpc17_sampleinit(void);
+static void lpc17_sdcard_sample(struct lpc17_sdcard_regs_s *regs);
+static void lpc17_sample(struct lpc17_dev_s *priv, int index);
+static void lpc17_sdcard_dump(struct lpc17_sdcard_regs_s *regs, const char *msg);
+static void lpc17_dumpsample(struct lpc17_dev_s *priv,
+ struct lpc17_sampleregs_s *regs, const char *msg);
+static void lpc17_dumpsamples(struct lpc17_dev_s *priv);
+#else
+# define lpc17_sampleinit()
+# define lpc17_sample(priv,index)
+# define lpc17_dumpsamples(priv)
+#endif
+
+#ifdef CONFIG_SDIO_DMA
+static void lpc17_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg);
+#endif
+
+/* Data Transfer Helpers ****************************************************/
+
+static uint8_t lpc17_log2(uint16_t value);
+static void lpc17_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl);
+static void lpc17_datadisable(void);
+static void lpc17_sendfifo(struct lpc17_dev_s *priv);
+static void lpc17_recvfifo(struct lpc17_dev_s *priv);
+static void lpc17_eventtimeout(int argc, uint32_t arg);
+static void lpc17_endwait(struct lpc17_dev_s *priv, sdio_eventset_t wkupevent);
+static void lpc17_endtransfer(struct lpc17_dev_s *priv, sdio_eventset_t wkupevent);
+
+/* Interrupt Handling *******************************************************/
+
+static int lpc17_interrupt(int irq, void *context);
+
+/* SD Card Interface Methods ************************************************/
+
+/* Mutual exclusion */
+
+#ifdef CONFIG_SDIO_MUXBUS
+static int lpc17_lock(FAR struct sdio_dev_s *dev, bool lock);
+#endif
+
+/* Initialization/setup */
+
+static void lpc17_reset(FAR struct sdio_dev_s *dev);
+static uint8_t lpc17_status(FAR struct sdio_dev_s *dev);
+static void lpc17_widebus(FAR struct sdio_dev_s *dev, bool enable);
+static void lpc17_clock(FAR struct sdio_dev_s *dev,
+ enum sdio_clock_e rate);
+static int lpc17_attach(FAR struct sdio_dev_s *dev);
+
+/* Command/Status/Data Transfer */
+
+static int lpc17_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t arg);
+static int lpc17_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
+ size_t nbytes);
+static int lpc17_sendsetup(FAR struct sdio_dev_s *dev,
+ FAR const uint8_t *buffer, uint32_t nbytes);
+static int lpc17_cancel(FAR struct sdio_dev_s *dev);
+
+static int lpc17_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd);
+static int lpc17_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t *rshort);
+static int lpc17_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t rlong[4]);
+static int lpc17_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t *rshort);
+static int lpc17_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd,
+ uint32_t *rnotimpl);
+
+/* EVENT handler */
+
+static void lpc17_waitenable(FAR struct sdio_dev_s *dev,
+ sdio_eventset_t eventset);
+static sdio_eventset_t
+ lpc17_eventwait(FAR struct sdio_dev_s *dev, uint32_t timeout);
+static void lpc17_callbackenable(FAR struct sdio_dev_s *dev,
+ sdio_eventset_t eventset);
+static int lpc17_registercallback(FAR struct sdio_dev_s *dev,
+ worker_t callback, void *arg);
+
+/* DMA */
+
+#ifdef CONFIG_SDIO_DMA
+static bool lpc17_dmasupported(FAR struct sdio_dev_s *dev);
+static int lpc17_dmarecvsetup(FAR struct sdio_dev_s *dev,
+ FAR uint8_t *buffer, size_t buflen);
+static int lpc17_dmasendsetup(FAR struct sdio_dev_s *dev,
+ FAR const uint8_t *buffer, size_t buflen);
+#endif
+
+/* Initialization/uninitialization/reset ************************************/
+
+static void lpc17_callback(void *arg);
+static void lpc17_default(void);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct lpc17_dev_s g_scard_dev =
+{
+ .dev =
+ {
+#ifdef CONFIG_SDIO_MUXBUS
+ .lock = lpc17_lock,
+#endif
+ .reset = lpc17_reset,
+ .status = lpc17_status,
+ .widebus = lpc17_widebus,
+ .clock = lpc17_clock,
+ .attach = lpc17_attach,
+ .sendcmd = lpc17_sendcmd,
+ .recvsetup = lpc17_recvsetup,
+ .sendsetup = lpc17_sendsetup,
+ .cancel = lpc17_cancel,
+ .waitresponse = lpc17_waitresponse,
+ .recvR1 = lpc17_recvshortcrc,
+ .recvR2 = lpc17_recvlong,
+ .recvR3 = lpc17_recvshort,
+ .recvR4 = lpc17_recvnotimpl,
+ .recvR5 = lpc17_recvnotimpl,
+ .recvR6 = lpc17_recvshortcrc,
+ .recvR7 = lpc17_recvshort,
+ .waitenable = lpc17_waitenable,
+ .eventwait = lpc17_eventwait,
+ .callbackenable = lpc17_callbackenable,
+ .registercallback = lpc17_registercallback,
+#ifdef CONFIG_SDIO_DMA
+ .dmasupported = lpc17_dmasupported,
+ .dmarecvsetup = lpc17_dmarecvsetup,
+ .dmasendsetup = lpc17_dmasendsetup,
+#endif
+ },
+};
+
+/* Register logging support */
+
+#ifdef CONFIG_DEBUG_SDIO
+static struct lpc17_sampleregs_s g_sampleregs[DEBUG_NSAMPLES];
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Low-level Helpers
+ ****************************************************************************/
+/****************************************************************************
+ * Name: lpc17_takesem
+ *
+ * Description:
+ * Take the wait semaphore (handling false alarm wakeups due to the receipt
+ * of signals).
+ *
+ * Input Parameters:
+ * dev - Instance of the SD card device driver state structure.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_takesem(struct lpc17_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: lpc17_setclock
+ *
+ * Description:
+ * Modify oft-changed bits in the CLKCR register. Only the following bit-
+ * fields are changed:
+ *
+ * CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, and HWFC_EN
+ *
+ * Input Parameters:
+ * clkcr - A new CLKCR setting for the above mentions bits (other bits
+ * are ignored.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static inline void lpc17_setclock(uint32_t clkcr)
+{
+ uint32_t regval = getreg32(LPC17_SDCARD_CLOCK);
+
+ /* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */
+
+ regval &= ~(SDCARD_CLOCK_CLKDIV_MASK|SDCARD_CLOCK_PWRSAV|SDCARD_CLOCK_BYPASS|
+ SDCARD_CLOCK_WIDBUS_MASK|SDCARD_CLOCK_NEGEDGE|SDCARD_CLOCK_HWFC_EN|
+ SDCARD_CLOCK_CLKEN);
+
+ /* Replace with user provided settings */
+
+ clkcr &= (SDCARD_CLOCK_CLKDIV_MASK|SDCARD_CLOCK_PWRSAV|SDCARD_CLOCK_BYPASS|
+ SDCARD_CLOCK_WIDBUS_MASK|SDCARD_CLOCK_NEGEDGE|SDCARD_CLOCK_HWFC_EN|
+ SDCARD_CLOCK_CLKEN);
+
+ regval |= clkcr;
+ putreg32(regval, LPC17_SDCARD_CLOCK);
+
+ fvdbg("CLKCR: %08x PWR: %08x\n",
+ getreg32(LPC17_SDCARD_CLOCK), getreg32(LPC17_SDCARD_PWR));
+}
+
+/****************************************************************************
+ * Name: lpc17_configwaitints
+ *
+ * Description:
+ * Enable/disable SD card interrupts needed to suport the wait function
+ *
+ * Input Parameters:
+ * priv - A reference to the SD card device state structure
+ * waitmask - The set of bits in the SD card MASK register to set
+ * waitevents - Waited for events
+ * wkupevent - Wake-up events
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_configwaitints(struct lpc17_dev_s *priv, uint32_t waitmask,
+ sdio_eventset_t waitevents,
+ sdio_eventset_t wkupevent)
+{
+ irqstate_t flags;
+
+ /* Save all of the data and set the new interrupt mask in one, atomic
+ * operation.
+ */
+
+ flags = irqsave();
+ priv->waitevents = waitevents;
+ priv->wkupevent = wkupevent;
+ priv->waitmask = waitmask;
+#ifdef CONFIG_SDIO_DMA
+ priv->xfrflags = 0;
+#endif
+ putreg32(priv->xfrmask | priv->waitmask, LPC17_SDCARD_MASK0);
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: lpc17_configxfrints
+ *
+ * Description:
+ * Enable SD card interrupts needed to support the data transfer event
+ *
+ * Input Parameters:
+ * priv - A reference to the SD card device state structure
+ * xfrmask - The set of bits in the SD card MASK register to set
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_configxfrints(struct lpc17_dev_s *priv, uint32_t xfrmask)
+{
+ irqstate_t flags;
+ flags = irqsave();
+ priv->xfrmask = xfrmask;
+ putreg32(priv->xfrmask | priv->waitmask, LPC17_SDCARD_MASK0);
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: lpc17_setpwrctrl
+ *
+ * Description:
+ * 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
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_setpwrctrl(uint32_t pwrctrl)
+{
+ uint32_t regval;
+
+ regval = getreg32(LPC17_SDCARD_PWR);
+ regval &= ~SDCARD_PWR_CTRL_MASK;
+ regval |= pwrctrl;
+ putreg32(regval, LPC17_SDCARD_PWR);
+}
+
+/****************************************************************************
+ * Name: lpc17_getpwrctrl
+ *
+ * Description:
+ * Return the current value of the the PWRCTRL field of the SD card P
+ * register. This function can be used to see the the SD card is power ON
+ * or OFF
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * The current value of the the PWRCTRL field of the SD card PWR register.
+ *
+ ****************************************************************************/
+
+static inline uint32_t lpc17_getpwrctrl(void)
+{
+ return getreg32(LPC17_SDCARD_PWR) & SDCARD_PWR_CTRL_MASK;
+}
+
+/****************************************************************************
+ * DMA Helpers
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lpc17_sampleinit
+ *
+ * Description:
+ * Setup prior to collecting DMA samples
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_SDIO
+static void lpc17_sampleinit(void)
+{
+ memset(g_sampleregs, 0xff, DEBUG_NSAMPLES * sizeof(struct lpc17_sampleregs_s));
+}
+#endif
+
+/****************************************************************************
+ * Name: lpc17_sdcard_sample
+ *
+ * Description:
+ * Sample SD card registers
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_SDIO
+static void lpc17_sdcard_sample(struct lpc17_sdcard_regs_s *regs)
+{
+ regs->pwr = (uint8_t)getreg32(LPC17_SDCARD_PWR);
+ regs->clkcr = (uint16_t)getreg32(LPC17_SDCARD_CLOCK);
+ regs->dctrl = (uint16_t)getreg32(LPC17_SDCARD_DCTRL);
+ regs->dtimer = getreg32(LPC17_SDCARD_DTIMER);
+ regs->dlen = getreg32(LPC17_SDCARD_DLEN);
+ regs->dcount = getreg32(LPC17_SDCARD_DCOUNT);
+ regs->sta = getreg32(LPC17_SDCARD_STATUS);
+ regs->mask = getreg32(LPC17_SDCARD_MASK0);
+ regs->fifocnt = getreg32(LPC17_SDCARD_FIFOCNT);
+}
+#endif
+
+/****************************************************************************
+ * Name: lpc17_sample
+ *
+ * Description:
+ * Sample SD card/DMA registers
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_SDIO
+static void lpc17_sample(struct lpc17_dev_s *priv, int index)
+{
+ struct lpc17_sampleregs_s *regs = &g_sampleregs[index];
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ if (priv->dmamode)
+ {
+ lpc17_dmasample(priv->dma, &regs->dma);
+ }
+#endif
+ lpc17_sdcard_sample(&regs->sdcard);
+}
+#endif
+
+/****************************************************************************
+ * Name: lpc17_sdcard_dump
+ *
+ * Description:
+ * Dump one register sample
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_SDIO
+static void lpc17_sdcard_dump(struct lpc17_sdcard_regs_s *regs, const char *msg)
+{
+ fdbg("SD Card Registers: %s\n", msg);
+ fdbg(" POWER[%08x]: %08x\n", LPC17_SDCARD_PWR, regs->pwr);
+ fdbg(" CLKCR[%08x]: %08x\n", LPC17_SDCARD_CLOCK, regs->clkcr);
+ fdbg(" DCTRL[%08x]: %08x\n", LPC17_SDCARD_DCTRL, regs->dctrl);
+ fdbg(" DTIMER[%08x]: %08x\n", LPC17_SDCARD_DTIMER, regs->dtimer);
+ fdbg(" DLEN[%08x]: %08x\n", LPC17_SDCARD_DLEN, regs->dlen);
+ fdbg(" DCOUNT[%08x]: %08x\n", LPC17_SDCARD_DCOUNT, regs->dcount);
+ fdbg(" STA[%08x]: %08x\n", LPC17_SDCARD_STATUS, regs->sta);
+ fdbg(" MASK[%08x]: %08x\n", LPC17_SDCARD_MASK0, regs->mask);
+ fdbg("FIFOCNT[%08x]: %08x\n", LPC17_SDCARD_FIFOCNT, regs->fifocnt);
+}
+#endif
+
+/****************************************************************************
+ * Name: lpc17_dumpsample
+ *
+ * Description:
+ * Dump one register sample
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_SDIO
+static void lpc17_dumpsample(struct lpc17_dev_s *priv,
+ struct lpc17_sampleregs_s *regs, const char *msg)
+{
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ if (priv->dmamode)
+ {
+ lpc17_dmadump(priv->dma, &regs->dma, msg);
+ }
+#endif
+ lpc17_sdcard_dump(&regs->sdcard, msg);
+}
+#endif
+
+/****************************************************************************
+ * Name: lpc17_dumpsamples
+ *
+ * Description:
+ * Dump all sampled register data
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_SDIO
+static void lpc17_dumpsamples(struct lpc17_dev_s *priv)
+{
+ lpc17_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP], "Before setup");
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ if (priv->dmamode)
+ {
+ lpc17_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_ENABLE], "Before DMA enable");
+ }
+#endif
+ lpc17_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP], "After setup");
+ lpc17_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER], "End of transfer");
+#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SDIO_DMA)
+ if (priv->dmamode)
+ {
+ lpc17_dumpsample(priv, &g_sampleregs[SAMPLENDX_DMA_CALLBACK], "DMA Callback");
+ }
+#endif
+}
+#endif
+
+/****************************************************************************
+ * Name: lpc17_dmacallback
+ *
+ * Description:
+ * Called when SD card DMA completes
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static void lpc17_dmacallback(DMA_HANDLE handle, uint8_t status, void *arg)
+{
+ FAR struct lpc17_dev_s *priv = (FAR struct lpc17_dev_s *)arg;
+ 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-
+ * Transfer.
+ */
+
+ lpc17_sample((struct lpc17_dev_s*)arg, SAMPLENDX_DMA_CALLBACK);
+
+ /* Get the result of the DMA transfer */
+
+ if ((status & DMA_STATUS_ERROR) != 0)
+ {
+ flldbg("DMA error %02x, remaining: %d\n", status, priv->remaining);
+ result = SDIOWAIT_ERROR;
+ }
+ else
+ {
+ result = SDIOWAIT_TRANSFERDONE;
+ }
+
+ /* Then terminate the transfer if this completes all of the steps in the
+ * transfer OR if a DMA error occurred. In the non-error case, we should
+ * already have the SD card transfer done interrupt. If not, the transfer
+ * will appropriately time out.
+ */
+
+ priv->xfrflags |= SDCARD_DMADONE_FLAG;
+ if (priv->xfrflags == SDCARD_ALLDONE || result == SDIOWAIT_ERROR)
+ {
+ lpc17_endtransfer(priv, result);
+ }
+}
+#endif
+
+/****************************************************************************
+ * Data Transfer Helpers
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lpc17_log2
+ *
+ * Description:
+ * Take (approximate) log base 2 of the provided number (Only works if the
+ * provided number is a power of 2).
+ *
+ ****************************************************************************/
+
+static uint8_t lpc17_log2(uint16_t value)
+{
+ uint8_t log2 = 0;
+
+ /* 0000 0000 0000 0001 -> return 0,
+ * 0000 0000 0000 001x -> return 1,
+ * 0000 0000 0000 01xx -> return 2,
+ * 0000 0000 0000 1xxx -> return 3,
+ * ...
+ * 1xxx xxxx xxxx xxxx -> return 15,
+ */
+
+ DEBUGASSERT(value > 0);
+ while (value != 1)
+ {
+ value >>= 1;
+ log2++;
+ }
+ return log2;
+}
+
+/****************************************************************************
+ * Name: lpc17_dataconfig
+ *
+ * Description:
+ * Configure the SD card data path for the next data transfer
+ *
+ ****************************************************************************/
+
+static void lpc17_dataconfig(uint32_t timeout, uint32_t dlen, uint32_t dctrl)
+{
+ uint32_t regval = 0;
+
+ /* Enable data path */
+
+ putreg32(timeout, LPC17_SDCARD_DTIMER); /* Set DTIMER */
+ putreg32(dlen, LPC17_SDCARD_DLEN); /* Set DLEN */
+
+ /* Configure DCTRL DTDIR, DTMODE, and DBLOCKSIZE fields and set the DTEN
+ * field
+ */
+
+ regval = getreg32(LPC17_SDCARD_DCTRL);
+ regval &= ~(SDCARD_DCTRL_DTDIR|SDCARD_DCTRL_DTMODE|SDCARD_DCTRL_DBLOCKSIZE_MASK);
+ dctrl &= (SDCARD_DCTRL_DTDIR|SDCARD_DCTRL_DTMODE|SDCARD_DCTRL_DBLOCKSIZE_MASK);
+ regval |= (dctrl|SDCARD_DCTRL_DTEN);
+ putreg32(regval, LPC17_SDCARD_DCTRL);
+}
+
+/****************************************************************************
+ * Name: lpc17_datadisable
+ *
+ * Description:
+ * Disable the the SD card data path setup by lpc17_dataconfig() and
+ * disable DMA.
+ *
+ ****************************************************************************/
+
+static void lpc17_datadisable(void)
+{
+ uint32_t regval;
+
+ /* Disable the data path */
+
+ putreg32(SDCARD_DTIMER_DATATIMEOUT, LPC17_SDCARD_DTIMER); /* Reset DTIMER */
+ putreg32(0, LPC17_SDCARD_DLEN); /* Reset DLEN */
+
+ /* Reset DCTRL DTEN, DTDIR, DTMODE, DMAEN, and DBLOCKSIZE fields */
+
+ regval = getreg32(LPC17_SDCARD_DCTRL);
+ regval &= ~(SDCARD_DCTRL_DTEN|SDCARD_DCTRL_DTDIR|SDCARD_DCTRL_DTMODE|
+ SDCARD_DCTRL_DMAEN|SDCARD_DCTRL_DBLOCKSIZE_MASK);
+ putreg32(regval, LPC17_SDCARD_DCTRL);
+}
+
+/****************************************************************************
+ * Name: lpc17_sendfifo
+ *
+ * Description:
+ * Send SD card data in interrupt mode
+ *
+ * Input Parameters:
+ * priv - An instance of the SD card device interface
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_sendfifo(struct lpc17_dev_s *priv)
+{
+ union
+ {
+ uint32_t w;
+ uint8_t b[4];
+ } data;
+
+ /* Loop while there is more data to be sent and the RX FIFO is not full */
+
+ while (priv->remaining > 0 &&
+ (getreg32(LPC17_SDCARD_STATUS) & SDCARD_STATUS_TXFIFOF) == 0)
+ {
+ /* Is there a full word remaining in the user buffer? */
+
+ if (priv->remaining >= sizeof(uint32_t))
+ {
+ /* Yes, transfer the word to the TX FIFO */
+
+ data.w = *priv->buffer++;
+ priv->remaining -= sizeof(uint32_t);
+ }
+ else
+ {
+ /* No.. transfer just the bytes remaining in the user buffer,
+ * padding with zero as necessary to extend to a full word.
+ */
+
+ uint8_t *ptr = (uint8_t *)priv->remaining;
+ int i;
+
+ data.w = 0;
+ for (i = 0; i < priv->remaining; i++)
+ {
+ data.b[i] = *ptr++;
+ }
+
+ /* Now the transfer is finished */
+
+ priv->remaining = 0;
+ }
+
+ /* Put the word in the FIFO */
+
+ putreg32(data.w, LPC17_SDCARD_FIFO);
+ }
+}
+
+/****************************************************************************
+ * Name: lpc17_recvfifo
+ *
+ * Description:
+ * Receive SD card data in interrupt mode
+ *
+ * Input Parameters:
+ * priv - An instance of the SD card device interface
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_recvfifo(struct lpc17_dev_s *priv)
+{
+ union
+ {
+ uint32_t w;
+ uint8_t b[4];
+ } data;
+
+ /* Loop while there is space to store the data and there is more
+ * data available in the RX FIFO.
+ */
+
+ while (priv->remaining > 0 &&
+ (getreg32(LPC17_SDCARD_STATUS) & SDCARD_STATUS_RXDAVL) != 0)
+ {
+ /* Read the next word from the RX FIFO */
+
+ data.w = getreg32(LPC17_SDCARD_FIFO);
+ if (priv->remaining >= sizeof(uint32_t))
+ {
+ /* Transfer the whole word to the user buffer */
+
+ *priv->buffer++ = data.w;
+ priv->remaining -= sizeof(uint32_t);
+ }
+ else
+ {
+ /* Transfer any trailing fractional word */
+
+ uint8_t *ptr = (uint8_t*)priv->buffer;
+ int i;
+
+ for (i = 0; i < priv->remaining; i++)
+ {
+ *ptr++ = data.b[i];
+ }
+
+ /* Now the transfer is finished */
+
+ priv->remaining = 0;
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: lpc17_eventtimeout
+ *
+ * Description:
+ * The watchdog timeout setup when the event wait start has expired without
+ * any other waited-for event occurring.
+ *
+ * Input Parameters:
+ * argc - The number of arguments (should be 1)
+ * arg - The argument (state structure reference cast to uint32_t)
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Always called from the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static void lpc17_eventtimeout(int argc, uint32_t arg)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s *)arg;
+
+ /* There is always race conditions with timer expirations. */
+
+ DEBUGASSERT((priv->waitevents & SDIOWAIT_TIMEOUT) != 0 || priv->wkupevent != 0);
+
+ /* Is a data transfer complete event expected? */
+
+ if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
+ {
+ /* Yes.. wake up any waiting threads */
+
+ lpc17_endwait(priv, SDIOWAIT_TIMEOUT);
+ flldbg("Timeout: remaining: %d\n", priv->remaining);
+ }
+}
+
+/****************************************************************************
+ * Name: lpc17_endwait
+ *
+ * Description:
+ * Wake up a waiting thread if the waited-for event has occurred.
+ *
+ * Input Parameters:
+ * priv - An instance of the SD card device interface
+ * wkupevent - The event that caused the wait to end
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Always called from the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static void lpc17_endwait(struct lpc17_dev_s *priv, sdio_eventset_t wkupevent)
+{
+ /* Cancel the watchdog timeout */
+
+ (void)wd_cancel(priv->waitwdog);
+
+ /* Disable event-related interrupts */
+
+ lpc17_configwaitints(priv, 0, 0, wkupevent);
+
+ /* Wake up the waiting thread */
+
+ lpc17_givesem(priv);
+}
+
+/****************************************************************************
+ * Name: lpc17_endtransfer
+ *
+ * Description:
+ * Terminate a transfer with the provided status. This function is called
+ * only from the SD card interrupt handler when end-of-transfer conditions
+ * are detected.
+ *
+ * Input Parameters:
+ * priv - An instance of the SD card device interface
+ * wkupevent - The event that caused the transfer to end
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Always called from the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static void lpc17_endtransfer(struct lpc17_dev_s *priv, sdio_eventset_t wkupevent)
+{
+ /* Disable all transfer related interrupts */
+
+ lpc17_configxfrints(priv, 0);
+
+ /* Clearing pending interrupt status on all transfer related interrupts */
+
+ putreg32(SDCARD_XFRDONE_ICR, LPC17_SDCARD_CLEAR);
+
+ /* If this was a DMA transfer, make sure that DMA is stopped */
+
+#ifdef CONFIG_SDIO_DMA
+ if (priv->dmamode)
+ {
+ /* DMA debug instrumentation */
+
+ lpc17_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).
+ */
+
+ lpc17_dmastop(priv->dma);
+ }
+#endif
+
+ /* Mark the transfer finished */
+
+ priv->remaining = 0;
+
+ /* Is a thread wait for these data transfer complete events? */
+
+ if ((priv->waitevents & wkupevent) != 0)
+ {
+ /* Yes.. wake up any waiting threads */
+
+ lpc17_endwait(priv, wkupevent);
+ }
+}
+
+/****************************************************************************
+ * Interrrupt Handling
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lpc17_interrupt
+ *
+ * Description:
+ * SD card interrupt handler
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static int lpc17_interrupt(int irq, void *context)
+{
+ struct lpc17_dev_s *priv = &g_scard_dev;
+ uint32_t enabled;
+ uint32_t pending;
+
+ /* Loop while there are pending interrupts. Check the SD card status
+ * register. Mask out all bits that don't correspond to enabled
+ * interrupts. (This depends on the fact that bits are ordered
+ * the same in both the STA and MASK register). If there are non-zero
+ * bits remaining, then we have work to do here.
+ */
+
+ while ((enabled = getreg32(LPC17_SDCARD_STATUS) & getreg32(LPC17_SDCARD_MASK0)) != 0)
+ {
+ /* Handle in progress, interrupt driven data transfers ****************/
+
+ pending = enabled & priv->xfrmask;
+ if (pending != 0)
+ {
+#ifdef CONFIG_SDIO_DMA
+ if (!priv->dmamode)
+#endif
+ {
+ /* Is the RX FIFO half full or more? Is so then we must be
+ * processing a receive transaction.
+ */
+
+ if ((pending & SDCARD_STATUS_RXFIFOHF) != 0)
+ {
+ /* Receive data from the RX FIFO */
+
+ lpc17_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!
+ */
+
+ else if ((pending & SDCARD_STATUS_TXFIFOHE) != 0)
+ {
+ /* Send data via the TX FIFO */
+
+ lpc17_sendfifo(priv);
+ }
+ }
+
+ /* Handle data end events */
+
+ if ((pending & SDCARD_STATUS_DATAEND) != 0)
+ {
+ /* Handle any data remaining the RX FIFO. If the RX FIFO is
+ * less than half full at the end of the transfer, then no
+ * half-full interrupt will be received.
+ */
+
+ /* Was this transfer performed in DMA mode? */
+
+#ifdef CONFIG_SDIO_DMA
+ if (priv->dmamode)
+ {
+ /* Yes.. Terminate the transfers only if the DMA has also
+ * finished.
+ */
+
+ priv->xfrflags |= SDCARD_XFRDONE_FLAG;
+ if (priv->xfrflags == SDCARD_ALLDONE)
+ {
+ lpc17_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
+ }
+
+ /* Otherwise, just disable futher transfer interrupts and
+ * wait for the DMA complete event.
+ */
+
+ else
+ {
+ lpc17_configxfrints(priv, 0);
+ }
+ }
+ else
+#endif
+ {
+ /* Receive data from the RX FIFO */
+
+ lpc17_recvfifo(priv);
+
+ /* Then terminate the transfer */
+
+ lpc17_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
+ }
+ }
+
+ /* Handle data block send/receive CRC failure */
+
+ else if ((pending & SDCARD_STATUS_DCRCFAIL) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: Data block CRC failure, remaining: %d\n", priv->remaining);
+ lpc17_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
+ }
+
+ /* Handle data timeout error */
+
+ else if ((pending & SDCARD_STATUS_DTIMEOUT) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: Data timeout, remaining: %d\n", priv->remaining);
+ lpc17_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_TIMEOUT);
+ }
+
+ /* Handle RX FIFO overrun error */
+
+ else if ((pending & SDCARD_STATUS_RXOVERR) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: RX FIFO overrun, remaining: %d\n", priv->remaining);
+ lpc17_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
+ }
+
+ /* Handle TX FIFO underrun error */
+
+ else if ((pending & SDCARD_STATUS_TXUNDERR) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: TX FIFO underrun, remaining: %d\n", priv->remaining);
+ lpc17_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
+ }
+
+ /* Handle start bit error */
+
+ else if ((pending & SDCARD_STATUS_STBITERR) != 0)
+ {
+ /* Terminate the transfer with an error */
+
+ flldbg("ERROR: Start bit, remaining: %d\n", priv->remaining);
+ lpc17_endtransfer(priv, SDIOWAIT_TRANSFERDONE|SDIOWAIT_ERROR);
+ }
+ }
+
+ /* Handle wait events *************************************************/
+
+ pending = enabled & priv->waitmask;
+ if (pending != 0)
+ {
+ /* Is this a response completion event? */
+
+ if ((pending & SDCARD_RESPDONE_STA) != 0)
+ {
+ /* Yes.. Is their a thread waiting for response done? */
+
+ if ((priv->waitevents & SDIOWAIT_RESPONSEDONE) != 0)
+ {
+ /* Yes.. wake the thread up */
+
+ putreg32(SDCARD_RESPDONE_ICR|SDCARD_CMDDONE_ICR, LPC17_SDCARD_CLEAR);
+ lpc17_endwait(priv, SDIOWAIT_RESPONSEDONE);
+ }
+ }
+
+ /* Is this a command completion event? */
+
+ if ((pending & SDCARD_CMDDONE_STA) != 0)
+ {
+ /* Yes.. Is their a thread waiting for command done? */
+
+ if ((priv->waitevents & SDIOWAIT_RESPONSEDONE) != 0)
+ {
+ /* Yes.. wake the thread up */
+
+ putreg32(SDCARD_CMDDONE_ICR, LPC17_SDCARD_CLEAR);
+ lpc17_endwait(priv, SDIOWAIT_CMDDONE);
+ }
+ }
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * SD card Interface Methods
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lpc17_lock
+ *
+ * Description:
+ * Locks the bus. Function calls low-level multiplexed bus routines to
+ * resolve bus requests and acknowledgment issues.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * lock - TRUE to lock, FALSE to unlock.
+ *
+ * Returned Value:
+ * OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_MUXBUS
+static int lpc17_lock(FAR struct sdio_dev_s *dev, bool lock)
+{
+ /* Single SD card instance so there is only one possibility. The multiplex
+ * bus is part of board support package.
+ */
+
+ lpc17_muxbus_sdio_lock(lock);
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: lpc17_reset
+ *
+ * Description:
+ * Reset the SD card controller. Undo all setup and initialization.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_reset(FAR struct sdio_dev_s *dev)
+{
+ FAR struct lpc17_dev_s *priv = (FAR struct lpc17_dev_s *)dev;
+ irqstate_t flags;
+
+ /* Disable clocking */
+
+ flags = irqsave();
+ putreg32(0, SDCARD_CLOCK_CLKEN_BB);
+ lpc17_setpwrctrl(SDCARD_PWR_CTRL_OFF);
+
+ /* Put SD card registers in their default, reset state */
+
+ lpc17_default();
+
+ /* Reset data */
+
+ priv->waitevents = 0; /* Set of events to be waited for */
+ priv->waitmask = 0; /* Interrupt enables for event waiting */
+ priv->wkupevent = 0; /* The event that caused the wakeup */
+#ifdef CONFIG_SDIO_DMA
+ priv->xfrflags = 0; /* Used to synchronize SD card and DMA completion events */
+#endif
+
+ wd_cancel(priv->waitwdog); /* Cancel any timeouts */
+
+ /* Interrupt mode data transfer support */
+
+ priv->buffer = 0; /* Address of current R/W buffer */
+ priv->remaining = 0; /* Number of bytes remaining in the transfer */
+ priv->xfrmask = 0; /* Interrupt enables for data transfer */
+
+ /* DMA data transfer support */
+
+ priv->widebus = false; /* Required for DMA support */
+#ifdef CONFIG_SDIO_DMA
+ priv->dmamode = false; /* true: DMA mode transfer */
+#endif
+
+ /* Configure the SD card peripheral */
+
+ lpc17_setclock(LPC17_CLCKCR_INIT | SDCARD_CLOCK_CLKEN);
+ lpc17_setpwrctrl(SDCARD_PWR_CTRL_ON);
+ irqrestore(flags);
+
+ fvdbg("CLCKR: %08x POWER: %08x\n",
+ getreg32(LPC17_SDCARD_CLOCK), getreg32(LPC17_SDCARD_PWR));
+}
+
+/****************************************************************************
+ * Name: lpc17_status
+ *
+ * Description:
+ * Get SD card status.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ *
+ * Returned Value:
+ * Returns a bitset of status values (see lpc17_status_* defines)
+ *
+ ****************************************************************************/
+
+static uint8_t lpc17_status(FAR struct sdio_dev_s *dev)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s *)dev;
+ return priv->cdstatus;
+}
+
+/****************************************************************************
+ * Name: lpc17_widebus
+ *
+ * Description:
+ * Called after change in Bus width has been selected (via ACMD6). Most
+ * controllers will need to perform some special operations to work
+ * correctly in the new bus mode.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * wide - true: wide bus (4-bit) bus mode enabled
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_widebus(FAR struct sdio_dev_s *dev, bool wide)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s *)dev;
+ priv->widebus = wide;
+}
+
+/****************************************************************************
+ * Name: lpc17_clock
+ *
+ * Description:
+ * Enable/disable SD card clocking
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * rate - Specifies the clocking to use (see enum sdio_clock_e)
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
+{
+ uint32_t clock;
+
+ switch (rate)
+ {
+ /* Disable clocking (with default ID mode divisor) */
+
+ default:
+ case CLOCK_SDCARD_DISABLED:
+ clock = LPC17_CLCKCR_INIT;
+ return;
+
+ /* Enable in initial ID mode clocking (<400KHz) */
+
+ case CLOCK_IDMODE:
+ clock = (LPC17_CLCKCR_INIT | SDCARD_CLOCK_CLKEN);
+ break;
+
+ /* Enable in MMC normal operation clocking */
+
+ case CLOCK_MMC_TRANSFER:
+ clock = (SDCARD_CLOCK_MMCXFR | SDCARD_CLOCK_CLKEN);
+ break;
+
+ /* SD normal operation clocking (wide 4-bit mode) */
+
+ case CLOCK_SD_TRANSFER_4BIT:
+#ifndef CONFIG_SDIO_WIDTH_D1_ONLY
+ clock = (SDCARD_CLOCK_SDWIDEXFR | SDCARD_CLOCK_CLKEN);
+ break;
+#endif
+
+ /* SD normal operation clocking (narrow 1-bit mode) */
+
+ case CLOCK_SD_TRANSFER_1BIT:
+ clock = (SDCARD_CLOCK_SDXFR | SDCARD_CLOCK_CLKEN);
+ break;
+ }
+
+ /* Set the new clock frequency along with the clock enable/disable bit */
+
+ lpc17_setclock(clock);
+}
+
+/****************************************************************************
+ * Name: lpc17_attach
+ *
+ * Description:
+ * Attach and prepare interrupts
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ *
+ * Returned Value:
+ * OK on success; A negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int lpc17_attach(FAR struct sdio_dev_s *dev)
+{
+ int ret;
+
+ /* Attach the SD card interrupt handler */
+
+ ret = irq_attach(LPC17_IRQ_SDCARD, lpc17_interrupt);
+ if (ret == OK)
+ {
+
+ /* Disable all interrupts at the SD card controller and clear static
+ * interrupt flags
+ */
+
+ putreg32(SDCARD_MASK0_RESET, LPC17_SDCARD_MASK0);
+ putreg32(SDCARD_CLEAR_STATICFLAGS, LPC17_SDCARD_CLEAR);
+
+ /* Enable SD card interrupts at the NVIC. They can now be enabled at
+ * the SD card controller as needed.
+ */
+
+ up_enable_irq(LPC17_IRQ_SDCARD);
+
+ /* Set the interrrupt priority */
+
+ up_prioritize_irq(LPC17_IRQ_SDCARD, CONFIG_SDCARD_PRI);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: lpc17_sendcmd
+ *
+ * Description:
+ * Send the SD card command
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * cmd - The command to send (32-bits, encoded)
+ * arg - 32-bit argument required with some commands
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static int lpc17_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
+{
+ uint32_t regval;
+ uint32_t cmdidx;
+
+ /* Set the SD card Argument value */
+
+ putreg32(arg, LPC17_SDCARD_ARG);
+
+ /* Clear CMDINDEX, WAITRESP, WAITINT, WAITPEND, and CPSMEN bits */
+
+ regval = getreg32(LPC17_SDCARD_CMD);
+ regval &= ~(SDCARD_CMD_INDEX_MASK|SDCARD_CMD_WAITRESP_MASK|
+ SDCARD_CMD_WAITINT|SDCARD_CMD_WAITPEND|SDCARD_CMD_CPSMEN);
+
+ /* Set WAITRESP bits */
+
+ switch (cmd & MMCSD_RESPONSE_MASK)
+ {
+ case MMCSD_NO_RESPONSE:
+ regval |= SDCARD_CMD_NORESPONSE;
+ break;
+
+ case MMCSD_R1_RESPONSE:
+ case MMCSD_R1B_RESPONSE:
+ case MMCSD_R3_RESPONSE:
+ case MMCSD_R4_RESPONSE:
+ case MMCSD_R5_RESPONSE:
+ case MMCSD_R6_RESPONSE:
+ case MMCSD_R7_RESPONSE:
+ regval |= SDCARD_CMD_SHORTRESPONSE;
+ break;
+
+ case MMCSD_R2_RESPONSE:
+ regval |= SDCARD_CMD_LONGRESPONSE;
+ break;
+ }
+
+ /* Set CPSMEN and the command index */
+
+ cmdidx = (cmd & MMCSD_CMDIDX_MASK) >> MMCSD_CMDIDX_SHIFT;
+ regval |= cmdidx | SDCARD_CMD_CPSMEN;
+
+ fvdbg("cmd: %08x arg: %08x regval: %08x\n", cmd, arg, regval);
+
+ /* Write the SD card CMD */
+
+ putreg32(SDCARD_RESPDONE_ICR|SDCARD_CMDDONE_ICR, LPC17_SDCARD_CLEAR);
+ putreg32(regval, LPC17_SDCARD_CMD);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lpc17_recvsetup
+ *
+ * Description:
+ * Setup hardware in preparation for data transfer from the card in non-DMA
+ * (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.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * buffer - Address of the buffer in which to receive the data
+ * nbytes - The number of bytes in the transfer
+ *
+ * Returned Value:
+ * Number of bytes sent on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int lpc17_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
+ size_t nbytes)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s *)dev;
+ uint32_t dblocksize;
+
+ DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0);
+ DEBUGASSERT(((uint32_t)buffer & 3) == 0);
+
+ /* Reset the DPSM configuration */
+
+ lpc17_datadisable();
+ lpc17_sampleinit();
+ lpc17_sample(priv, SAMPLENDX_BEFORE_SETUP);
+
+ /* Save the destination buffer information for use by the interrupt handler */
+
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = nbytes;
+#ifdef CONFIG_SDIO_DMA
+ priv->dmamode = false;
+#endif
+
+ /* Then set up the SD card data path */
+
+ dblocksize = lpc17_log2(nbytes) << SDCARD_DCTRL_DBLOCKSIZE_SHIFT;
+ lpc17_dataconfig(SDCARD_DTIMER_DATATIMEOUT, nbytes, dblocksize|SDCARD_DCTRL_DTDIR);
+
+ /* And enable interrupts */
+
+ lpc17_configxfrints(priv, SDCARD_RECV_MASK);
+ lpc17_sample(priv, SAMPLENDX_AFTER_SETUP);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lpc17_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.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * buffer - Address of the buffer containing the data to send
+ * nbytes - The number of bytes in the transfer
+ *
+ * Returned Value:
+ * Number of bytes sent on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int lpc17_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer,
+ size_t nbytes)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s *)dev;
+ uint32_t dblocksize;
+
+ DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0);
+ DEBUGASSERT(((uint32_t)buffer & 3) == 0);
+
+ /* Reset the DPSM configuration */
+
+ lpc17_datadisable();
+ lpc17_sampleinit();
+ lpc17_sample(priv, SAMPLENDX_BEFORE_SETUP);
+
+ /* Save the source buffer information for use by the interrupt handler */
+
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = nbytes;
+#ifdef CONFIG_SDIO_DMA
+ priv->dmamode = false;
+#endif
+
+ /* Then set up the SD card data path */
+
+ dblocksize = lpc17_log2(nbytes) << SDCARD_DCTRL_DBLOCKSIZE_SHIFT;
+ lpc17_dataconfig(SDCARD_DTIMER_DATATIMEOUT, nbytes, dblocksize);
+
+ /* Enable TX interrrupts */
+
+ lpc17_configxfrints(priv, SDCARD_SEND_MASK);
+ lpc17_sample(priv, SAMPLENDX_AFTER_SETUP);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lpc17_cancel
+ *
+ * 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.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ *
+ * Returned Value:
+ * OK is success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int lpc17_cancel(FAR struct sdio_dev_s *dev)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s*)dev;
+
+ /* Disable all transfer- and event- related interrupts */
+
+ lpc17_configxfrints(priv, 0);
+ lpc17_configwaitints(priv, 0, 0, 0);
+
+ /* Clearing pending interrupt status on all transfer- and event- related
+ * interrupts
+ */
+
+ putreg32(SDCARD_WAITALL_ICR, LPC17_SDCARD_CLEAR);
+
+ /* Cancel any watchdog timeout */
+
+ (void)wd_cancel(priv->waitwdog);
+
+ /* If this was a DMA transfer, make sure that DMA is stopped */
+
+#ifdef CONFIG_SDIO_DMA
+ 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.
+ */
+
+ lpc17_dmastop(priv->dma);
+ }
+#endif
+
+ /* Mark no transfer in progress */
+
+ priv->remaining = 0;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lpc17_waitresponse
+ *
+ * Description:
+ * Poll-wait for the response to the last command to be ready.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * cmd - The command that was sent. See 32-bit command definitions above.
+ *
+ * Returned Value:
+ * OK is success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int lpc17_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
+{
+ int32_t timeout;
+ uint32_t events;
+
+ switch (cmd & MMCSD_RESPONSE_MASK)
+ {
+ case MMCSD_NO_RESPONSE:
+ events = SDCARD_CMDDONE_STA;
+ timeout = SDCARD_CMDTIMEOUT;
+ break;
+
+ case MMCSD_R1_RESPONSE:
+ case MMCSD_R1B_RESPONSE:
+ case MMCSD_R2_RESPONSE:
+ case MMCSD_R6_RESPONSE:
+ events = SDCARD_RESPDONE_STA;
+ timeout = SDCARD_LONGTIMEOUT;
+ break;
+
+ case MMCSD_R4_RESPONSE:
+ case MMCSD_R5_RESPONSE:
+ return -ENOSYS;
+
+ case MMCSD_R3_RESPONSE:
+ case MMCSD_R7_RESPONSE:
+ events = SDCARD_RESPDONE_STA;
+ timeout = SDCARD_CMDTIMEOUT;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Then wait for the response (or timeout) */
+
+ while ((getreg32(LPC17_SDCARD_STATUS) & events) == 0)
+ {
+ if (--timeout <= 0)
+ {
+ fdbg("ERROR: Timeout cmd: %08x events: %08x STA: %08x\n",
+ cmd, events, getreg32(LPC17_SDCARD_STATUS));
+
+ return -ETIMEDOUT;
+ }
+ }
+
+ putreg32(SDCARD_CMDDONE_ICR, LPC17_SDCARD_CLEAR);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lpc17_recvRx
+ *
+ * Description:
+ * Receive response to SD card command. Only the critical payload is
+ * returned -- that is 32 bits for 48 bit status and 128 bits for 136 bit
+ * status. The driver implementation should verify the correctness of
+ * the remaining, non-returned bits (CRCs, CMD index, etc.).
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * Rx - Buffer in which to receive the response
+ *
+ * Returned Value:
+ * Number of bytes sent on success; a negated errno on failure. Here a
+ * failure means only a faiure to obtain the requested reponse (due to
+ * transport problem -- timeout, CRC, etc.). The implementation only
+ * assures that the response is returned intacta and does not check errors
+ * within the response itself.
+ *
+ ****************************************************************************/
+
+static int lpc17_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort)
+{
+#ifdef CONFIG_DEBUG
+ uint32_t respcmd;
+#endif
+ uint32_t regval;
+ int ret = OK;
+
+ /* R1 Command response (48-bit)
+ * 47 0 Start bit
+ * 46 0 Transmission bit (0=from card)
+ * 45:40 bit5 - bit0 Command index (0-63)
+ * 39:8 bit31 - bit0 32-bit card status
+ * 7:1 bit6 - bit0 CRC7
+ * 0 1 End bit
+ *
+ * R1b Identical to R1 with the additional busy signaling via the data
+ * line.
+ *
+ * R6 Published RCA Response (48-bit, SD card only)
+ * 47 0 Start bit
+ * 46 0 Transmission bit (0=from card)
+ * 45:40 bit5 - bit0 Command index (0-63)
+ * 39:8 bit31 - bit0 32-bit Argument Field, consisting of:
+ * [31:16] New published RCA of card
+ * [15:0] Card status bits {23,22,19,12:0}
+ * 7:1 bit6 - bit0 CRC7
+ * 0 1 End bit
+ */
+
+
+#ifdef CONFIG_DEBUG
+ if (!rshort)
+ {
+ fdbg("ERROR: rshort=NULL\n");
+ ret = -EINVAL;
+ }
+
+ /* Check that this is the correct response to this command */
+
+ else if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1_RESPONSE &&
+ (cmd & MMCSD_RESPONSE_MASK) != MMCSD_R1B_RESPONSE &&
+ (cmd & MMCSD_RESPONSE_MASK) != MMCSD_R6_RESPONSE)
+ {
+ fdbg("ERROR: Wrong response CMD=%08x\n", cmd);
+ ret = -EINVAL;
+ }
+ else
+#endif
+ {
+ /* Check if a timeout or CRC error occurred */
+
+ regval = getreg32(LPC17_SDCARD_STATUS);
+ if ((regval & SDCARD_STATUS_CTIMEOUT) != 0)
+ {
+ fdbg("ERROR: Command timeout: %08x\n", regval);
+ ret = -ETIMEDOUT;
+ }
+ else if ((regval & SDCARD_STATUS_CCRCFAIL) != 0)
+ {
+ fdbg("ERROR: CRC failure: %08x\n", regval);
+ ret = -EIO;
+ }
+#ifdef CONFIG_DEBUG
+ else
+ {
+ /* Check response received is of desired command */
+
+ respcmd = getreg32(LPC17_SDCARD_RESPCMD);
+ if ((uint8_t)(respcmd & SDCARD_RESPCMD_MASK) != (cmd & MMCSD_CMDIDX_MASK))
+ {
+ fdbg("ERROR: RESCMD=%02x CMD=%08x\n", respcmd, cmd);
+ ret = -EINVAL;
+ }
+ }
+#endif
+ }
+
+ /* Clear all pending message completion events and return the R1/R6 response */
+
+ putreg32(SDCARD_RESPDONE_ICR|SDCARD_CMDDONE_ICR, LPC17_SDCARD_CLEAR);
+ *rshort = getreg32(LPC17_SDCARD_RESP0);
+ return ret;
+}
+
+static int lpc17_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t rlong[4])
+{
+ uint32_t regval;
+ int ret = OK;
+
+ /* R2 CID, CSD register (136-bit)
+ * 135 0 Start bit
+ * 134 0 Transmission bit (0=from card)
+ * 133:128 bit5 - bit0 Reserved
+ * 127:1 bit127 - bit1 127-bit CID or CSD register
+ * (including internal CRC)
+ * 0 1 End bit
+ */
+
+#ifdef CONFIG_DEBUG
+ /* Check that R1 is the correct response to this command */
+
+ if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R2_RESPONSE)
+ {
+ fdbg("ERROR: Wrong response CMD=%08x\n", cmd);
+ ret = -EINVAL;
+ }
+ else
+#endif
+ {
+ /* Check if a timeout or CRC error occurred */
+
+ regval = getreg32(LPC17_SDCARD_STATUS);
+ if (regval & SDCARD_STATUS_CTIMEOUT)
+ {
+ fdbg("ERROR: Timeout STA: %08x\n", regval);
+ ret = -ETIMEDOUT;
+ }
+ else if (regval & SDCARD_STATUS_CCRCFAIL)
+ {
+ fdbg("ERROR: CRC fail STA: %08x\n", regval);
+ ret = -EIO;
+ }
+ }
+
+ /* Return the long response */
+
+ putreg32(SDCARD_RESPDONE_ICR|SDCARD_CMDDONE_ICR, LPC17_SDCARD_CLEAR);
+ if (rlong)
+ {
+ rlong[0] = getreg32(LPC17_SDCARD_RESP0);
+ rlong[1] = getreg32(LPC17_SDCARD_RESP1);
+ rlong[2] = getreg32(LPC17_SDCARD_RESP2);
+ rlong[3] = getreg32(LPC17_SDCARD_RESP4);
+ }
+ return ret;
+}
+
+static int lpc17_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rshort)
+{
+ uint32_t regval;
+ int ret = OK;
+
+ /* R3 OCR (48-bit)
+ * 47 0 Start bit
+ * 46 0 Transmission bit (0=from card)
+ * 45:40 bit5 - bit0 Reserved
+ * 39:8 bit31 - bit0 32-bit OCR register
+ * 7:1 bit6 - bit0 Reserved
+ * 0 1 End bit
+ */
+
+ /* Check that this is the correct response to this command */
+
+#ifdef CONFIG_DEBUG
+ if ((cmd & MMCSD_RESPONSE_MASK) != MMCSD_R3_RESPONSE &&
+ (cmd & MMCSD_RESPONSE_MASK) != MMCSD_R7_RESPONSE)
+ {
+ fdbg("ERROR: Wrong response CMD=%08x\n", cmd);
+ ret = -EINVAL;
+ }
+ else
+#endif
+ {
+ /* Check if a timeout occurred (Apparently a CRC error can terminate
+ * a good response)
+ */
+
+ regval = getreg32(LPC17_SDCARD_STATUS);
+ if (regval & SDCARD_STATUS_CTIMEOUT)
+ {
+ fdbg("ERROR: Timeout STA: %08x\n", regval);
+ ret = -ETIMEDOUT;
+ }
+ }
+
+ putreg32(SDCARD_RESPDONE_ICR|SDCARD_CMDDONE_ICR, LPC17_SDCARD_CLEAR);
+ if (rshort)
+ {
+ *rshort = getreg32(LPC17_SDCARD_RESP0);
+ }
+ return ret;
+}
+
+/* MMC responses not supported */
+
+static int lpc17_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t *rnotimpl)
+{
+ putreg32(SDCARD_RESPDONE_ICR|SDCARD_CMDDONE_ICR, LPC17_SDCARD_CLEAR);
+ return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: lpc17_waitenable
+ *
+ * Description:
+ * Enable/disable of a set of SD card wait events. This is part of the
+ * the SDCARD_WAITEVENT sequence. The set of to-be-waited-for events is
+ * configured before calling lpc17_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) SDCARD_WAITENABLE is called
+ * again specifying a different set of wait events, or (2) SDCARD_EVENTWAIT
+ * returns.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * eventset - A bitset of events to enable or disable (see SDIOWAIT_*
+ * definitions). 0=disable; 1=enable.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_waitenable(FAR struct sdio_dev_s *dev,
+ sdio_eventset_t eventset)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s*)dev;
+ uint32_t waitmask;
+
+ DEBUGASSERT(priv != NULL);
+
+ /* Disable event-related interrupts */
+
+ lpc17_configwaitints(priv, 0, 0, 0);
+
+ /* Select the interrupt mask that will give us the appropriate wakeup
+ * interrupts.
+ */
+
+ waitmask = 0;
+ if ((eventset & SDIOWAIT_CMDDONE) != 0)
+ {
+ waitmask |= SDCARD_CMDDONE_MASK;
+ }
+
+ if ((eventset & SDIOWAIT_RESPONSEDONE) != 0)
+ {
+ waitmask |= SDCARD_RESPDONE_MASK;
+ }
+
+ if ((eventset & SDIOWAIT_TRANSFERDONE) != 0)
+ {
+ waitmask |= SDCARD_XFRDONE_MASK;
+ }
+
+ /* Enable event-related interrupts */
+
+ putreg32(SDCARD_WAITALL_ICR, LPC17_SDCARD_CLEAR);
+ lpc17_configwaitints(priv, waitmask, eventset, 0);
+}
+
+/****************************************************************************
+ * Name: lpc17_eventwait
+ *
+ * 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_eventwait
+ * returns. SDCARD_WAITEVENTS must be called again before lpc17_eventwait
+ * can be used again.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ * timeout - Maximum time in milliseconds to wait. Zero means immediate
+ * timeout with no wait. The timeout value is ignored if
+ * SDIOWAIT_TIMEOUT is not included in the waited-for eventset.
+ *
+ * Returned Value:
+ * Event set containing the event(s) that ended the wait. Should always
+ * be non-zero. All events are disabled after the wait concludes.
+ *
+ ****************************************************************************/
+
+static sdio_eventset_t lpc17_eventwait(FAR struct sdio_dev_s *dev,
+ uint32_t timeout)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s*)dev;
+ sdio_eventset_t wkupevent = 0;
+ irqstate_t flags;
+ int ret;
+
+ /* There is a race condition here... the event may have completed before
+ * we get here. In this case waitevents will be zero, but wkupevents will
+ * be non-zero (and, hopefully, the semaphore count will also be non-zero.
+ */
+
+ flags = irqsave();
+ DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
+
+ /* Check if the timeout event is specified in the event set */
+
+ if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
+ {
+ int delay;
+
+ /* Yes.. Handle a cornercase: The user request a timeout event but
+ * with timeout == 0?
+ */
+
+ if (!timeout)
+ {
+ /* Then just tell the caller that we already timed out */
+
+ wkupevent = SDIOWAIT_TIMEOUT;
+ goto errout;
+ }
+
+ /* Start the watchdog timer */
+
+ delay = (timeout + (MSEC_PER_TICK-1)) / MSEC_PER_TICK;
+ ret = wd_start(priv->waitwdog, delay, (wdentry_t)lpc17_eventtimeout,
+ 1, (uint32_t)priv);
+ if (ret != OK)
+ {
+ fdbg("ERROR: wd_start failed: %d\n", ret);
+ }
+ }
+
+ /* Loop until the event (or the timeout occurs). Race conditions are avoided
+ * by calling lpc17_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.
+ */
+
+ lpc17_takesem(priv);
+ 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.
+ */
+
+ if (wkupevent != 0)
+ {
+ /* Yes... break out of the loop with wkupevent non-zero */
+
+ break;
+ }
+ }
+
+ /* Disable event-related interrupts */
+
+ lpc17_configwaitints(priv, 0, 0, 0);
+#ifdef CONFIG_SDIO_DMA
+ priv->xfrflags = 0;
+#endif
+
+errout:
+ irqrestore(flags);
+ lpc17_dumpsamples(priv);
+ return wkupevent;
+}
+
+/****************************************************************************
+ * Name: lpc17_callbackenable
+ *
+ * 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_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 SD card device interface
+ * eventset - A bitset of events to enable or disable (see SDIOMEDIA_*
+ * definitions). 0=disable; 1=enable.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void lpc17_callbackenable(FAR struct sdio_dev_s *dev,
+ sdio_eventset_t eventset)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s*)dev;
+
+ fvdbg("eventset: %02x\n", eventset);
+ DEBUGASSERT(priv != NULL);
+
+ priv->cbevents = eventset;
+ lpc17_callback(priv);
+}
+
+/****************************************************************************
+ * Name: lpc17_registercallback
+ *
+ * Description:
+ * Register a callback that that will be invoked on any media status
+ * change. Callbacks should not be made from interrupt handlers, rather
+ * 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 SDCARD_CALLBACKENABLE
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * callback - The funtion to call on the media change
+ * arg - A caller provided value to return with the callback
+ *
+ * Returned Value:
+ * 0 on success; negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int lpc17_registercallback(FAR struct sdio_dev_s *dev,
+ worker_t callback, void *arg)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s*)dev;
+
+ /* Disable callbacks and register this callback and is argument */
+
+ fvdbg("Register %p(%p)\n", callback, arg);
+ DEBUGASSERT(priv != NULL);
+
+ priv->cbevents = 0;
+ priv->cbarg = arg;
+ priv->callback = callback;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: lpc17_dmasupported
+ *
+ * Description:
+ * Return true if the hardware can support DMA
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card device interface
+ *
+ * Returned Value:
+ * true if DMA is supported.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static bool lpc17_dmasupported(FAR struct sdio_dev_s *dev)
+{
+ return true;
+}
+#endif
+
+/****************************************************************************
+ * Name: lpc17_dmarecvsetup
+ *
+ * Description:
+ * 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 SD card 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
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static int lpc17_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
+ size_t buflen)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s *)dev;
+ uint32_t dblocksize;
+ int ret = -EINVAL;
+
+ DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
+ DEBUGASSERT(((uint32_t)buffer & 3) == 0);
+
+ /* Reset the DPSM configuration */
+
+ lpc17_datadisable();
+
+ /* Wide bus operation is required for DMA */
+
+ if (priv->widebus)
+ {
+ lpc17_sampleinit();
+ lpc17_sample(priv, SAMPLENDX_BEFORE_SETUP);
+
+ /* Save the destination buffer information for use by the interrupt handler */
+
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = buflen;
+ priv->dmamode = true;
+
+ /* Then set up the SD card data path */
+
+ dblocksize = lpc17_log2(buflen) << SDCARD_DCTRL_DBLOCKSIZE_SHIFT;
+ lpc17_dataconfig(SDCARD_DTIMER_DATATIMEOUT, buflen, dblocksize|SDCARD_DCTRL_DTDIR);
+
+ /* Configure the RX DMA */
+
+ lpc17_configxfrints(priv, SDCARD_DMARECV_MASK);
+
+ putreg32(1, SDCARD_DCTRL_DMAEN_BB);
+ lpc17_dmasetup(priv->dma, LPC17_SDCARD_FIFO, (uint32_t)buffer,
+ (buflen + 3) >> 2, SDCARD_RXDMA32_CONFIG);
+
+ /* Start the DMA */
+
+ lpc17_sample(priv, SAMPLENDX_BEFORE_ENABLE);
+ lpc17_dmastart(priv->dma, lpc17_dmacallback, priv, false);
+ lpc17_sample(priv, SAMPLENDX_AFTER_SETUP);
+ ret = OK;
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: lpc17_dmasendsetup
+ *
+ * Description:
+ * 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 SD card 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
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static int lpc17_dmasendsetup(FAR struct sdio_dev_s *dev,
+ FAR const uint8_t *buffer, size_t buflen)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s *)dev;
+ uint32_t dblocksize;
+ int ret = -EINVAL;
+
+ DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
+ DEBUGASSERT(((uint32_t)buffer & 3) == 0);
+
+ /* Reset the DPSM configuration */
+
+ lpc17_datadisable();
+
+ /* Wide bus operation is required for DMA */
+
+ if (priv->widebus)
+ {
+ lpc17_sampleinit();
+ lpc17_sample(priv, SAMPLENDX_BEFORE_SETUP);
+
+ /* Save the source buffer information for use by the interrupt handler */
+
+ priv->buffer = (uint32_t*)buffer;
+ priv->remaining = buflen;
+ priv->dmamode = true;
+
+ /* Then set up the SD card data path */
+
+ dblocksize = lpc17_log2(buflen) << SDCARD_DCTRL_DBLOCKSIZE_SHIFT;
+ lpc17_dataconfig(SDCARD_DTIMER_DATATIMEOUT, buflen, dblocksize);
+
+ /* Configure the TX DMA */
+
+ lpc17_dmasetup(priv->dma, LPC17_SDCARD_FIFO, (uint32_t)buffer,
+ (buflen + 3) >> 2, SDCARD_TXDMA32_CONFIG);
+
+ lpc17_sample(priv, SAMPLENDX_BEFORE_ENABLE);
+ putreg32(1, SDCARD_DCTRL_DMAEN_BB);
+
+ /* Start the DMA */
+
+ lpc17_dmastart(priv->dma, lpc17_dmacallback, priv, false);
+ lpc17_sample(priv, SAMPLENDX_AFTER_SETUP);
+
+ /* Enable TX interrrupts */
+
+ lpc17_configxfrints(priv, SDCARD_DMASEND_MASK);
+
+ ret = OK;
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Initialization/uninitialization/reset
+ ****************************************************************************/
+/****************************************************************************
+ * Name: lpc17_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 lpc17_callback(void *arg)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s*)arg;
+
+ /* Is a callback registered? */
+
+ DEBUGASSERT(priv != NULL);
+ fvdbg("Callback %p(%p) cbevents: %02x cdstatus: %02x\n",
+ priv->callback, priv->cbarg, priv->cbevents, priv->cdstatus);
+
+ if (priv->callback)
+ {
+ /* Yes.. Check for enabled callback events */
+
+ if ((priv->cdstatus & SDCARD_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;
+
+ /* 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 */
+
+ fvdbg("Queuing callback to %p(%p)\n", priv->callback, priv->cbarg);
+ (void)work_queue(HPWORK, &priv->cbwork, (worker_t)priv->callback, priv->cbarg, 0);
+ }
+ else
+ {
+ /* No.. then just call the callback here */
+
+ fvdbg("Callback to %p(%p)\n", priv->callback, priv->cbarg);
+ priv->callback(priv->cbarg);
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: lpc17_default
+ *
+ * Description:
+ * Restore SD card registers to their default, reset values
+ *
+ ****************************************************************************/
+
+static void lpc17_default(void)
+{
+ putreg32(SDCARD_PWR_RESET, LPC17_SDCARD_PWR);
+ putreg32(SDCARD_CLOCK_RESET, LPC17_SDCARD_CLOCK);
+ putreg32(SDCARD_ARG_RESET, LPC17_SDCARD_ARG);
+ putreg32(SDCARD_CMD_RESET, LPC17_SDCARD_CMD);
+ putreg32(SDCARD_DTIMER_RESET, LPC17_SDCARD_DTIMER);
+ putreg32(SDCARD_DLEN_RESET, LPC17_SDCARD_DLEN);
+ putreg32(SDCARD_DCTRL_RESET, LPC17_SDCARD_DCTRL);
+ putreg32(SDCARD_CLEAR_RESET, LPC17_SDCARD_CLEAR);
+ putreg32(SDCARD_MASK0_RESET, LPC17_SDCARD_MASK0);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sdio_initialize
+ *
+ * Description:
+ * Initialize SD card for operation.
+ *
+ * Input Parameters:
+ * slotno - Not used.
+ *
+ * Returned Values:
+ * A reference to an SD card interface structure. NULL is returned on failures.
+ *
+ ****************************************************************************/
+
+FAR struct sdio_dev_s *sdio_initialize(int slotno)
+{
+ /* There is only one slot */
+
+ struct lpc17_dev_s *priv = &g_scard_dev;
+
+ /* Initialize the SD card slot structure */
+
+ sem_init(&priv->waitsem, 0, 0);
+ priv->waitwdog = wd_create();
+ DEBUGASSERT(priv->waitwdog);
+
+ /* Allocate a DMA channel */
+
+#ifdef CONFIG_SDIO_DMA
+ priv->dma = lpc17_dmachannel(SDCARD_DMACHAN);
+ DEBUGASSERT(priv->dma);
+#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).
+ *
+ * If bus is multiplexed then there is a custom bus configuration utility
+ * in the scope of the board support package.
+ */
+
+#ifndef CONFIG_SDIO_MUXBUS
+ lpc17_configgpio(GPIO_SDCARD_D0);
+#ifndef CONFIG_SDIO_WIDTH_D1_ONLY
+ lpc17_configgpio(GPIO_SDCARD_D1);
+ lpc17_configgpio(GPIO_SDCARD_D2);
+ lpc17_configgpio(GPIO_SDCARD_D3);
+#endif
+ lpc17_configgpio(GPIO_SDCARD_CK);
+ lpc17_configgpio(GPIO_SDCARD_CMD);
+#endif
+
+ /* Reset the card and assure that it is in the initial, unconfigured
+ * state.
+ */
+
+ lpc17_reset(&priv->dev);
+ return &g_scard_dev.dev;
+}
+
+/****************************************************************************
+ * Name: sdio_mediachange
+ *
+ * Description:
+ * Called by board-specific logic -- posssible from an interrupt handler --
+ * in order to signal to the driver that a card has been inserted or
+ * removed from the slot
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card driver device state structure.
+ * cardinslot - true is a card has been detected in the slot; false if a
+ * card has been removed from the slot. Only transitions
+ * (inserted->removed or removed->inserted should be reported)
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s *)dev;
+ uint8_t cdstatus;
+ irqstate_t flags;
+
+ /* Update card status */
+
+ flags = irqsave();
+ cdstatus = priv->cdstatus;
+ if (cardinslot)
+ {
+ priv->cdstatus |= SDCARD_STATUS_PRESENT;
+ }
+ else
+ {
+ priv->cdstatus &= ~SDCARD_STATUS_PRESENT;
+ }
+ fvdbg("cdstatus OLD: %02x NEW: %02x\n", cdstatus, priv->cdstatus);
+
+ /* Perform any requested callback if the status has changed */
+
+ if (cdstatus != priv->cdstatus)
+ {
+ lpc17_callback(priv);
+ }
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: sdio_wrprotect
+ *
+ * Description:
+ * Called by board-specific logic to report if the card in the slot is
+ * mechanically write protected.
+ *
+ * Input Parameters:
+ * dev - An instance of the SD card driver device state structure.
+ * wrprotect - true is a card is writeprotected.
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect)
+{
+ struct lpc17_dev_s *priv = (struct lpc17_dev_s *)dev;
+ irqstate_t flags;
+
+ /* Update card status */
+
+ flags = irqsave();
+ if (wrprotect)
+ {
+ priv->cdstatus |= SDCARD_STATUS_WRPROTECTED;
+ }
+ else
+ {
+ priv->cdstatus &= ~SDCARD_STATUS_WRPROTECTED;
+ }
+ fvdbg("cdstatus: %02x\n", priv->cdstatus);
+ irqrestore(flags);
+}
+#endif /* CONFIG_LPC17_SDCARD */
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_sdcard.h b/nuttx/arch/arm/src/lpc17xx/lpc17_sdcard.h
new file mode 100644
index 000000000..3cb4132b2
--- /dev/null
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_sdcard.h
@@ -0,0 +1,127 @@
+/************************************************************************************
+ * arch/arm/src/lpc17xx/lpc17_sdcard.h
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_LPC17XX_LPC17_SDCARD_H
+#define __ARCH_ARM_SRC_LPC17XX_LPC17_SDCARD_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdbool.h>
+
+#include "chip.h"
+#include "chip/lpc17_sdcard.h"
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C" {
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: sdio_initialize
+ *
+ * Description:
+ * Initialize SDIO for operation.
+ *
+ * Input Parameters:
+ * slotno - Not used.
+ *
+ * Returned Values:
+ * A reference to an SDIO interface structure. NULL is returned on failures.
+ *
+ ****************************************************************************/
+
+struct sdio_dev_s; /* See include/nuttx/sdio.h */
+FAR struct sdio_dev_s *sdio_initialize(int slotno);
+
+/****************************************************************************
+ * Name: sdio_mediachange
+ *
+ * Description:
+ * Called by board-specific logic -- posssible from an interrupt handler --
+ * in order to signal to the driver that a card has been inserted or
+ * removed from the slot
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO driver device state structure.
+ * cardinslot - true is a card has been detected in the slot; false if a
+ * card has been removed from the slot. Only transitions
+ * (inserted->removed or removed->inserted should be reported)
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot);
+
+/****************************************************************************
+ * Name: sdio_wrprotect
+ *
+ * Description:
+ * Called by board-specific logic to report if the card in the slot is
+ * mechanically write protected.
+ *
+ * Input Parameters:
+ * dev - An instance of the SDIO driver device state structure.
+ * wrprotect - true is a card is writeprotected.
+ *
+ * Returned Values:
+ * None
+ *
+ ****************************************************************************/
+
+void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_ARM_SRC_LPC17XX_LPC17_SDCARD_H */
+