summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-08-22 15:42:10 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-08-22 15:42:10 +0000
commitfd891fceaf3c9852a361c70705d44e1ba7c4a38e (patch)
tree77b99409525c8dff5bb51edd1135042485f2fa74
parent75ae6a7cb1ffba04cd6c697cbc8679c0fc80b943 (diff)
downloadpx4-nuttx-fd891fceaf3c9852a361c70705d44e1ba7c4a38e.tar.gz
px4-nuttx-fd891fceaf3c9852a361c70705d44e1ba7c4a38e.tar.bz2
px4-nuttx-fd891fceaf3c9852a361c70705d44e1ba7c4a38e.zip
Progress with Kinetis SDHC driver (more to to)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3904 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/Documentation/NuttxPortingGuide.html14
-rw-r--r--nuttx/arch/arm/src/kinetis/kinetis_sdhc.c211
-rwxr-xr-xnuttx/arch/arm/src/sam3u/sam3u_hsmci.c5
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_sdio.c5
-rwxr-xr-xnuttx/configs/kwikstik-k40/src/up_nsh.c13
-rw-r--r--nuttx/configs/twr-k60n512/src/twrk60-internal.h1
-rw-r--r--nuttx/configs/twr-k60n512/src/up_nsh.c7
-rw-r--r--nuttx/drivers/mmcsd/mmcsd_sdio.c30
-rw-r--r--nuttx/include/nuttx/sdio.h7
9 files changed, 183 insertions, 110 deletions
diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html
index 2fda4d612..4289e9146 100644
--- a/nuttx/Documentation/NuttxPortingGuide.html
+++ b/nuttx/Documentation/NuttxPortingGuide.html
@@ -2760,6 +2760,16 @@ extern void up_ledoff(int led);
That structure defines a call table with the following methods:
</p>
<p>
+ Mutual exclusion:
+ </p>
+ <ul>
+ <p>
+ <code>#ifdef CONFIG_SDIO_MUXBUS</code><br>
+ <code> int (*lock)(FAR struct sdio_dev_s *dev, bool lock);</code><br>
+ <code>#endif</code>
+ </p>
+ </ul>
+ <p>
Initialization/setup:
</p>
<ul>
@@ -2767,13 +2777,13 @@ extern void up_ledoff(int led);
<code>uint8_t (*status)(FAR struct sdio_dev_s *dev);</code><br>
<code>void (*widebus)(FAR struct sdio_dev_s *dev, bool enable);</code><br>
<code>void (*clock)(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate);</code><br>
- <code>int (*attach)(FAR struct sdio_dev_s *dev);</code></p>
+ <code>int (*attach)(FAR struct sdio_dev_s *dev);</code><br>
</ul>
<p>
Command/Status/Data Transfer:
</p>
<ul>
- <p><code>void (*sendcmd)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg);</code><br>
+ <p><code>int (*sendcmd)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg);</code><br>
<code>int (*recvsetup)(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, size_t nbytes);</code><br>
<code>int (*sendsetup)(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, size_t nbytes);</code><br>
<code>int (*cancel)(FAR struct sdio_dev_s *dev);</code><br>
diff --git a/nuttx/arch/arm/src/kinetis/kinetis_sdhc.c b/nuttx/arch/arm/src/kinetis/kinetis_sdhc.c
index 2e31824bc..d758c5590 100644
--- a/nuttx/arch/arm/src/kinetis/kinetis_sdhc.c
+++ b/nuttx/arch/arm/src/kinetis/kinetis_sdhc.c
@@ -153,11 +153,11 @@
/* Event waiting interrupt mask bits */
-#define SDHC_CMDDONE_INTS (SDHC_INT_CC)
-#define SDHC_RESPDONE_INTS (SDHC_INT_CCE|SDHC_INT_CTOE|SDHC_INT_CEBE|SDHC_INT_CIE)
+#define SDHC_RESPERR_INTS (SDHC_INT_CCE|SDHC_INT_CTOE|SDHC_INT_CEBE|SDHC_INT_CIE)
+#define SDHC_RESPDONE_INTS (SDHC_RESPERR_INTS|SDHC_INT_CC)
#define SDHC_XFDONE_INTS (SDHC_INT_DCE|SDHC_INT_DTOE|SDHC_INT_DEBE)
-#define SDHC_WAITALL_INTS (SDHC_CMDDONE_INTS|SDHC_RESPDONE_INTS|SDHC_XFDONE_INTS)
+#define SDHC_WAITALL_INTS (SDHC_RESPDONE_INTS|SDHC_XFDONE_INTS)
/* Let's wait until we have both SDIO transfer complete and DMA complete. */
@@ -338,7 +338,7 @@ static int kinetis_attach(FAR struct sdio_dev_s *dev);
/* Command/Status/Data Transfer */
-static void kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
+static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t arg);
static int kinetis_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
size_t nbytes);
@@ -1241,35 +1241,17 @@ static int kinetis_interrupt(int irq, void *context)
{
/* Yes.. Is their a thread waiting for response done? */
- if ((priv->waitevents & SDIOWAIT_RESPONSEDONE) != 0)
+ if ((priv->waitevents & (SDIOWAIT_CMDDONE|SDIOWAIT_RESPONSEDONE)) != 0)
{
/* Yes.. mask further interrupts and wake the thread up */
regval = getreg32(KINETIS_SDHC_IRQSIGEN);
- regval &= ~(SDHC_RESPDONE_INTS|SDHC_CMDDONE_INTS);
+ regval &= ~SDHC_RESPDONE_INTS;
putreg32(regval, KINETIS_SDHC_IRQSIGEN);
kinetis_endwait(priv, SDIOWAIT_RESPONSEDONE);
}
}
-
- /* Is this a command completion event? */
-
- if ((pending & SDHC_CMDDONE_INTS) != 0)
- {
- /* Yes.. Is their a thread waiting for command done? */
-
- if ((priv->waitevents & SDIOWAIT_RESPONSEDONE) != 0)
- {
- /* Yes.. mask further interrupts and wake the thread up */
-
- regval = getreg32(KINETIS_SDHC_IRQSIGEN);
- regval &= ~SDHC_CMDDONE_INTS;
- putreg32(regval, KINETIS_SDHC_IRQSIGEN);
-
- kinetis_endwait(priv, SDIOWAIT_CMDDONE);
- }
- }
}
/* Re-enable card interrupts */
@@ -1350,18 +1332,9 @@ static void kinetis_reset(FAR struct sdio_dev_s *dev)
while ((getreg32(KINETIS_SDHC_SYSCTL) & SDHC_SYSCTL_RSTA) != 0);
- /* Set the initially SDCLK frequency to around 400KHz */
+ /* Make sure that all clocking is disabled */
- kinetis_clock(dev, CLOCK_IDMODE);
-
- /* Configure IO pad to set the power voltage of external card to around
- * 3.0V.
- */
-#warning "Missing logic"
-
- /* Poll bits CIHB and CDIHB bits of PRSSTAT to wait both bits are cleared. */
-
- while ((getreg32(KINETIS_SDHC_PRSSTAT) & (SDHC_PRSSTAT_CIHB|SDHC_PRSSTAT_CDIHB)) != 0);
+ kinetis_clock(dev, CLOCK_SDIO_DISABLED);
/* Enable all status bits (these could not all be potential sources of
* interrupts.
@@ -1565,11 +1538,18 @@ static void kinetis_frequency(FAR struct sdio_dev_s *dev, uint32_t frequency)
prescaled = frequency / prescaler;
divisor = (prescaled + (frequency >> 1)) / frequency;
- /* Set the new divisor information in the SYSCTRL register */
+ /* Set the new divisor information and enable all clocks in the SYSCTRL
+ * register.
+ *
+ * TODO: Investigate using the automatically gated clocks to reduce power
+ * consumption.
+ */
regval = getreg32(KINETIS_SDHC_SYSCTL);
regval &= ~(SDHC_SYSCTL_SDCLKFS_MASK|SDHC_SYSCTL_DVS_MASK);
- regval |= (sdclkfs | SDHC_SYSCTL_DVS_DIV(divisor) | SDHC_SYSCTL_SDCLKEN);
+ regval |= (sdclkfs | SDHC_SYSCTL_DVS_DIV(divisor));
+ regval |= (SDHC_SYSCTL_SDCLKEN|SDHC_SYSCTL_PEREN|SDHC_SYSCTL_HCKEN|
+ SDHC_SYSCTL_IPGEN);
putreg32(regval, KINETIS_SDHC_SYSCTL);
fvdbg("SYSCTRL: %08x\n", getreg32(KINETIS_SDHC_SYSCTL));
}
@@ -1596,13 +1576,28 @@ static void kinetis_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
uint32_t frequency;
uint32_t regval;
+ /* The SDCLK must be disabled before its frequency can be changed: "SDCLK
+ * frequency can be changed when this bit is 0. Then, the host controller
+ * shall maintain the same clock frequency until SDCLK is stopped (stop at
+ * SDCLK = 0).
+ */
+
+ regval = getreg32(KINETIS_SDHC_SYSCTL);
+ regval &= ~SDHC_SYSCTL_SDCLKEN;
+ putreg32(regval, KINETIS_SDHC_SYSCTL);
+ fvdbg("SYSCTRL: %08x\n", getreg32(KINETIS_SDHC_SYSCTL));
+
switch (rate)
{
default:
case CLOCK_SDIO_DISABLED : /* Clock is disabled */
{
- regval = getreg32(KINETIS_SDHC_SYSCTL);
- regval &= ~(SDHC_SYSCTL_SDCLKFS_MASK|SDHC_SYSCTL_DVS_MASK|SDHC_SYSCTL_SDCLKEN);
+ /* Clear the prescaler and divisor settings and other clock
+ * enables as well.
+ */
+
+ regval &= ~(SDHC_SYSCTL_IPGEN|SDHC_SYSCTL_HCKEN|SDHC_SYSCTL_PEREN|
+ SDHC_SYSCTL_SDCLKFS_MASK|SDHC_SYSCTL_DVS_MASK);
putreg32(regval, KINETIS_SDHC_SYSCTL);
fvdbg("SYSCTRL: %08x\n", getreg32(KINETIS_SDHC_SYSCTL));
return;
@@ -1636,37 +1631,71 @@ static void kinetis_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
{
uint32_t regval;
+ /* The SDCLK must be disabled before its frequency can be changed: "SDCLK
+ * frequency can be changed when this bit is 0. Then, the host controller
+ * shall maintain the same clock frequency until SDCLK is stopped (stop at
+ * SDCLK = 0).
+ */
+
regval = getreg32(KINETIS_SDHC_SYSCTL);
- regval &= ~(SDHC_SYSCTL_SDCLKFS_MASK|SDHC_SYSCTL_DVS_MASK|SDHC_SYSCTL_SDCLKEN);
+ regval &= ~SDHC_SYSCTL_SDCLKEN;
+ putreg32(regval, KINETIS_SDHC_SYSCTL);
+ fvdbg("SYSCTRL: %08x\n", getreg32(KINETIS_SDHC_SYSCTL));
+
+ /* Clear the old prescaler and divisor values so that new ones can be ORed
+ * in.
+ */
+
+ regval &= ~(SDHC_SYSCTL_SDCLKFS_MASK|SDHC_SYSCTL_DVS_MASK);
+
+ /* Select the new prescaler and divisor values based on the requested mode
+ * and the settings from the board.h file.
+ *
+ * TODO: Investigate using the automatically gated clocks to reduce power
+ * consumption.
+ */
switch (rate)
{
default:
case CLOCK_SDIO_DISABLED : /* Clock is disabled */
- break;
+ {
+ /* Clear the prescaler and divisor settings and other clock
+ * enables as well.
+ */
+
+ regval &= ~(SDHC_SYSCTL_IPGEN|SDHC_SYSCTL_HCKEN|SDHC_SYSCTL_PEREN);
+ putreg32(regval, KINETIS_SDHC_SYSCTL);
+ fvdbg("SYSCTRL: %08x\n", getreg32(KINETIS_SDHC_SYSCTL));
+ return;
+ }
case CLOCK_IDMODE : /* Initial ID mode clocking (<400KHz) */
regval |= (BOARD_SDHC_IDMODE_PRESCALER|BOARD_SDHC_IDMODE_DIVISOR|
- SDHC_SYSCTL_SDCLKEN);
+ SDHC_SYSCTL_SDCLKEN|SDHC_SYSCTL_PEREN|SDHC_SYSCTL_HCKEN|
+ SDHC_SYSCTL_IPGEN);
break;
case CLOCK_MMC_TRANSFER : /* MMC normal operation clocking */
regval |= (BOARD_SDHC_MMCMODE_PRESCALER|BOARD_SDHC_MMCMODE_DIVISOR|
- SDHC_SYSCTL_SDCLKEN);
+ SDHC_SYSCTL_SDCLKEN|SDHC_SYSCTL_PEREN|SDHC_SYSCTL_HCKEN|
+ SDHC_SYSCTL_IPGEN);
break;
case CLOCK_SD_TRANSFER_1BIT : /* SD normal operation clocking (narrow
* 1-bit mode) */
#ifndef CONFIG_SDIO_WIDTH_D1_ONLY
regval |= (BOARD_SDHC_SD1MODE_PRESCALER|BOARD_SDHC_IDMODE_DIVISOR|
- SDHC_SYSCTL_SDCLKEN);
+ SDHC_SYSCTL_SDCLKEN|SDHC_SYSCTL_PEREN|SDHC_SYSCTL_HCKEN|
+ SDHC_SYSCTL_IPGEN);
break;
#endif
case CLOCK_SD_TRANSFER_4BIT : /* SD normal operation clocking (wide
* 4-bit mode) */
regval |= (BOARD_SDHC_SD4MODE_PRESCALER|BOARD_SDHC_SD4MODE_DIVISOR|
- SDHC_SYSCTL_SDCLKEN);
+ SDHC_SYSCTL_SDCLKEN|SDHC_SYSCTL_PEREN|SDHC_SYSCTL_HCKEN|
+ SDHC_SYSCTL_IPGEN);
break;
}
@@ -1736,10 +1765,11 @@ static int kinetis_attach(FAR struct sdio_dev_s *dev)
*
****************************************************************************/
-static void kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
+static int kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
{
uint32_t regval;
uint32_t cmdidx;
+ int32_t timeout;
/* Initialize the command index */
@@ -1853,15 +1883,37 @@ static void kinetis_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t a
fvdbg("cmd: %08x arg: %08x regval: %08x\n", cmd, arg, regval);
+ /* The Command Inhibit (CIHB) bit is set in the PRSSTAT bit immediately
+ * after the transfer type register is written. This bit is cleared when
+ * the command response is received. If this status bit is 0, it
+ * indicates that the CMD line is not in use and the SDHC can issue a
+ * SD/MMC Command using the CMD line.
+ *
+ * CIHB should always be set when this function is called.
+ */
+
+ timeout = SDHC_CMDTIMEOUT;
+ while ((getreg32(KINETIS_SDHC_PRSSTAT) & SDHC_PRSSTAT_CIHB) != 0)
+ {
+ if (--timeout <= 0)
+ {
+ fdbg("ERROR: Timeout cmd: %08x PRSSTAT: %08x\n",
+ cmd, getreg32(KINETIS_SDHC_PRSSTAT));
+
+ return -EBUSY;
+ }
+ }
+
/* Set the SDHC Argument value */
putreg32(arg, KINETIS_SDHC_CMDARG);
/* Enable appropriate interrupts and write the SDHC CMD */
- putreg32(SDHC_RESPDONE_INTS|SDHC_CMDDONE_INTS|SDHC_INT_CINT,
- KINETIS_SDHC_IRQSIGEN);
+ putreg32(SDHC_RESPDONE_INTS, KINETIS_SDHC_IRQSTAT);
+ putreg32(SDHC_RESPDONE_INTS|SDHC_INT_CINT, KINETIS_SDHC_IRQSIGEN);
putreg32(regval, KINETIS_SDHC_XFERTYP);
+ return OK;
}
/****************************************************************************
@@ -2034,7 +2086,10 @@ static int kinetis_cancel(FAR struct sdio_dev_s *dev)
* Name: kinetis_waitresponse
*
* Description:
- * Poll-wait for the response to the last command to be ready.
+ * Poll-wait for the response to the last command to be ready. This
+ * function should be called even after sending commands that have no
+ * response (such as CMD0) to make sure that the hardware is ready to
+ * receive the next command.
*
* Input Parameters:
* dev - An instance of the SDIO device interface
@@ -2047,22 +2102,23 @@ static int kinetis_cancel(FAR struct sdio_dev_s *dev)
static int kinetis_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
{
- int32_t timeout;
- uint32_t events;
+ uint32_t errors;
+ int32_t timeout;
+ int ret = OK;
switch (cmd & MMCSD_RESPONSE_MASK)
{
case MMCSD_NO_RESPONSE:
- events = SDHC_CMDDONE_INTS;
timeout = SDHC_CMDTIMEOUT;
- break;
+ errors = 0;
+ return OK;
case MMCSD_R1_RESPONSE:
case MMCSD_R1B_RESPONSE:
case MMCSD_R2_RESPONSE:
case MMCSD_R6_RESPONSE:
- events = SDHC_RESPDONE_INTS;
timeout = SDHC_LONGTIMEOUT;
+ errors = SDHC_RESPERR_INTS;
break;
case MMCSD_R4_RESPONSE:
@@ -2071,29 +2127,43 @@ static int kinetis_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
case MMCSD_R3_RESPONSE:
case MMCSD_R7_RESPONSE:
- events = SDHC_RESPDONE_INTS;
timeout = SDHC_CMDTIMEOUT;
+ errors = SDHC_RESPERR_INTS;
break;
default:
return -EINVAL;
}
- /* Then wait for the response (or timeout) */
+ /* Then wait for the Command Complete (CC) indication (or timeout). The
+ * CC bit is set when the end bit of the command response is received
+ * (except Auto CMD12).
+ */
- while ((getreg32(KINETIS_SDHC_IRQSTAT) & events) == 0)
+ while ((getreg32(KINETIS_SDHC_IRQSTAT) & SDHC_INT_CC) == 0)
{
if (--timeout <= 0)
{
- fdbg("ERROR: Timeout cmd: %08x events: %08x IRQSTAT: %08x\n",
- cmd, events, getreg32(KINETIS_SDHC_IRQSTAT));
+ fdbg("ERROR: Timeout cmd: %08x IRQSTAT: %08x\n",
+ cmd, getreg32(KINETIS_SDHC_IRQSTAT));
return -ETIMEDOUT;
}
}
- putreg32(SDHC_CMDDONE_INTS, KINETIS_SDHC_IRQSTAT);
- return OK;
+ /* Check for hardware detected errors */
+
+ if ((getreg32(KINETIS_SDHC_IRQSTAT) & errors) != 0)
+ {
+ fdbg("ERROR: cmd: %08x errors: %08x IRQSTAT: %08x\n",
+ cmd, errors, getreg32(KINETIS_SDHC_IRQSTAT));
+ ret = -EIO;
+ }
+
+ /* Clear the response wait status bits */
+
+ putreg32(SDHC_RESPDONE_INTS, KINETIS_SDHC_IRQSTAT);
+ return ret;
}
/****************************************************************************
@@ -2182,7 +2252,7 @@ static int kinetis_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32
/* Clear all pending message completion events and return the R1/R6 response */
- putreg32(SDHC_RESPDONE_INTS|SDHC_CMDDONE_INTS, KINETIS_SDHC_IRQSTAT);
+ putreg32(SDHC_RESPDONE_INTS, KINETIS_SDHC_IRQSTAT);
*rshort = getreg32(KINETIS_SDHC_CMDRSP0);
return ret;
}
@@ -2230,7 +2300,7 @@ static int kinetis_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t r
/* Disable interrupts and return the long response */
regval = getreg32(KINETIS_SDHC_IRQSIGEN);
- regval &= ~(SDHC_RESPDONE_INTS|SDHC_CMDDONE_INTS);
+ regval &= ~SDHC_RESPDONE_INTS;
putreg32(regval, KINETIS_SDHC_IRQSIGEN);
if (rlong)
@@ -2286,7 +2356,7 @@ static int kinetis_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t
/* Disable interrupts and return the short response */
regval = getreg32(KINETIS_SDHC_IRQSIGEN);
- regval &= ~(SDHC_RESPDONE_INTS|SDHC_CMDDONE_INTS);
+ regval &= ~SDHC_RESPDONE_INTS;
putreg32(regval, KINETIS_SDHC_IRQSIGEN);
if (rshort)
@@ -2305,7 +2375,7 @@ static int kinetis_recvnotimpl(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_
/* Disable interrupts and return an error */
regval = getreg32(KINETIS_SDHC_IRQSIGEN);
- regval &= ~(SDHC_RESPDONE_INTS|SDHC_CMDDONE_INTS);
+ regval &= ~SDHC_RESPDONE_INTS;
putreg32(regval, KINETIS_SDHC_IRQSIGEN);
return -ENOSYS;
@@ -2353,12 +2423,7 @@ static void kinetis_waitenable(FAR struct sdio_dev_s *dev,
*/
waitints = 0;
- if ((eventset & SDIOWAIT_CMDDONE) != 0)
- {
- waitints |= SDHC_CMDDONE_INTS;
- }
-
- if ((eventset & SDIOWAIT_RESPONSEDONE) != 0)
+ if ((eventset & (SDIOWAIT_CMDDONE|SDIOWAIT_RESPONSEDONE)) != 0)
{
waitints |= SDHC_RESPDONE_INTS;
}
@@ -2835,7 +2900,9 @@ FAR struct sdio_dev_s *sdhc_initialize(int slotno)
priv->dma = kinetis_dmachannel(DMACHAN_SDHC);
#endif
- /* Enable clocking to the SDHC module. */
+ /* Enable clocking to the SDHC module. Clocking is still diabled in
+ * the SYSCTRL register.
+ */
regval = getreg32(KINETIS_SIM_SCGC3);
regval |= SIM_SCGC3_SDHC;
diff --git a/nuttx/arch/arm/src/sam3u/sam3u_hsmci.c b/nuttx/arch/arm/src/sam3u/sam3u_hsmci.c
index 1ab0dbc75..b7872a219 100755
--- a/nuttx/arch/arm/src/sam3u/sam3u_hsmci.c
+++ b/nuttx/arch/arm/src/sam3u/sam3u_hsmci.c
@@ -393,7 +393,7 @@ static int sam3u_attach(FAR struct sdio_dev_s *dev);
/* Command/Status/Data Transfer */
-static void sam3u_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
+static int sam3u_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t arg);
static void sam3u_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen,
unsigned int nblocks);
@@ -1464,7 +1464,7 @@ static int sam3u_attach(FAR struct sdio_dev_s *dev)
*
****************************************************************************/
-static void sam3u_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
+static int sam3u_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
{
struct sam3u_dev_s *priv = (struct sam3u_dev_s*)dev;
uint32_t regval;
@@ -1571,6 +1571,7 @@ static void sam3u_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg
fvdbg("cmd: %08x arg: %08x regval: %08x\n", cmd, arg, regval);
putreg32(regval, SAM3U_HSMCI_CMDR);
sam3u_cmdsample1(SAMPLENDX_AFTER_CMDR);
+ return OK;
}
/****************************************************************************
diff --git a/nuttx/arch/arm/src/stm32/stm32_sdio.c b/nuttx/arch/arm/src/stm32/stm32_sdio.c
index 3a3e3827e..34a0f9ba2 100644
--- a/nuttx/arch/arm/src/stm32/stm32_sdio.c
+++ b/nuttx/arch/arm/src/stm32/stm32_sdio.c
@@ -334,7 +334,7 @@ static int stm32_attach(FAR struct sdio_dev_s *dev);
/* Command/Status/Data Transfer */
-static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
+static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
uint32_t arg);
static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
size_t nbytes);
@@ -1574,7 +1574,7 @@ static int stm32_attach(FAR struct sdio_dev_s *dev)
*
****************************************************************************/
-static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
+static int stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg)
{
uint32_t regval;
uint32_t cmdidx;
@@ -1623,6 +1623,7 @@ static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg
putreg32(SDIO_RESPDONE_ICR|SDIO_CMDDONE_ICR, STM32_SDIO_ICR);
putreg32(regval, STM32_SDIO_CMD);
+ return OK;
}
/****************************************************************************
diff --git a/nuttx/configs/kwikstik-k40/src/up_nsh.c b/nuttx/configs/kwikstik-k40/src/up_nsh.c
index b1ccdf60f..c4e027c6b 100755
--- a/nuttx/configs/kwikstik-k40/src/up_nsh.c
+++ b/nuttx/configs/kwikstik-k40/src/up_nsh.c
@@ -172,15 +172,6 @@ static void kinetis_mediachange(void)
g_nsh.inserted = inserted;
sdhc_mediachange(g_nsh.sdhc, inserted);
-
- /* If the card has been inserted, then check if it is write protected
- * aw well.
- */
-
- if (inserted)
- {
- sdhc_wrprotect(g_nsh.sdhc, !kinetis_gpioread(GPIO_SD_WRPROTECT));
- }
}
}
#endif
@@ -228,10 +219,6 @@ int nsh_archinitialize(void)
kinetis_pinconfig(GPIO_SD_CARDDETECT);
kinetis_pinirqattach(GPIO_SD_CARDDETECT, kinetis_cdinterrupt);
- /* Configure the write protect GPIO */
-
- kinetis_pinconfig(GPIO_SD_WRPROTECT);
-
/* Mount the SDHC-based MMC/SD block driver */
/* First, get an instance of the SDHC interface */
diff --git a/nuttx/configs/twr-k60n512/src/twrk60-internal.h b/nuttx/configs/twr-k60n512/src/twrk60-internal.h
index eb4555b57..df60daae4 100644
--- a/nuttx/configs/twr-k60n512/src/twrk60-internal.h
+++ b/nuttx/configs/twr-k60n512/src/twrk60-internal.h
@@ -111,7 +111,6 @@
#define GPIO_SD_CARDDETECT (GPIO_PULLUP | PIN_INT_BOTH | PIN_PORTE | PIN28)
#define GPIO_SD_WRPROTECT (GPIO_PULLUP | PIN_PORTE | PIN27)
-#define GPIO_SD_CARDON (GPIO_HIGHDRIVE | GPIO_OUTPUT_ZER0 | PIN_PORTE | PIN6)
#define GPIO_SW1 (GPIO_PULLUP | PIN_INT_BOTH | PIN_PORTA | PIN19)
#define GPIO_SW2 (GPIO_PULLUP | PIN_INT_BOTH | PIN_PORTE | PIN26)
diff --git a/nuttx/configs/twr-k60n512/src/up_nsh.c b/nuttx/configs/twr-k60n512/src/up_nsh.c
index 1fc959cf9..4feaed506 100644
--- a/nuttx/configs/twr-k60n512/src/up_nsh.c
+++ b/nuttx/configs/twr-k60n512/src/up_nsh.c
@@ -216,12 +216,7 @@ int nsh_archinitialize(void)
#ifdef CONFIG_NSH_HAVEMMCSD
int ret;
- /* Configure GPIO pins.
- *
- * First CD power. The initial state will provide SD power.
- */
-
- kinetis_pinconfig(GPIO_SD_CARDON); /* Applies power to the card */
+ /* Configure GPIO pins */
/* Attached the card detect interrupt (but don't enable it yet) */
diff --git a/nuttx/drivers/mmcsd/mmcsd_sdio.c b/nuttx/drivers/mmcsd/mmcsd_sdio.c
index 27232983e..a7d2bee0f 100644
--- a/nuttx/drivers/mmcsd/mmcsd_sdio.c
+++ b/nuttx/drivers/mmcsd/mmcsd_sdio.c
@@ -318,20 +318,22 @@ static int mmcsd_sendcmdpoll(FAR struct mmcsd_state_s *priv, uint32_t cmd,
/* Send the command */
- SDIO_SENDCMD(priv->dev, cmd, arg);
-
- /* Then poll-wait until the response is available */
-
- ret = SDIO_WAITRESPONSE(priv->dev, cmd);
- if (ret != OK)
+ ret = SDIO_SENDCMD(priv->dev, cmd, arg);
+ if (ret == OK)
{
- fdbg("ERROR: Wait for response to cmd: %08x failed: %d\n", cmd, ret);
+ /* Then poll-wait until the response is available */
+
+ ret = SDIO_WAITRESPONSE(priv->dev, cmd);
+ if (ret != OK)
+ {
+ fdbg("ERROR: Wait for response to cmd: %08x failed: %d\n", cmd, ret);
+ }
}
return ret;
}
/****************************************************************************
- * Name: mmcsd_sendcmdpoll
+ * Name: mmcsd_sendcmd4
*
* Description:
* Set the Driver Stage Register (DSR) if (1) a CONFIG_MMCSD_DSR has been
@@ -2475,8 +2477,16 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv)
* CMD8 Response: R7
*/
- mmcsd_sendcmdpoll(priv, SD_CMD8, MMCSD_CMD8CHECKPATTERN|MMCSD_CMD8VOLTAGE_27);
- ret = SDIO_RECVR7(priv->dev, SD_CMD8, &response);
+ ret = mmcsd_sendcmdpoll(priv, SD_CMD8, MMCSD_CMD8CHECKPATTERN|MMCSD_CMD8VOLTAGE_27);
+ if (ret == OK)
+ {
+ /* CMD8 was sent successfully... Get the R7 response */
+
+ ret = SDIO_RECVR7(priv->dev, SD_CMD8, &response);
+ }
+
+ /* Were both the command sent and response received correctly? */
+
if (ret == OK)
{
/* CMD8 succeeded this is probably a SDHC card. Verify the operating
diff --git a/nuttx/include/nuttx/sdio.h b/nuttx/include/nuttx/sdio.h
index df31ed79e..fdb674dca 100644
--- a/nuttx/include/nuttx/sdio.h
+++ b/nuttx/include/nuttx/sdio.h
@@ -529,7 +529,10 @@
* Name: SDIO_WAITRESPONSE
*
* Description:
- * Poll-wait for the response to the last command to be ready.
+ * Poll-wait for the response to the last command to be ready. This
+ * function should be called even after sending commands that have no
+ * response (such as CMD0) to make sure that the hardware is ready to
+ * receive the next command.
*
* Input Parameters:
* dev - An instance of the SDIO device interface
@@ -790,7 +793,7 @@ struct sdio_dev_s
/* Command/Status/Data Transfer */
- void (*sendcmd)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg);
+ int (*sendcmd)(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg);
#ifdef CONFIG_SDIO_BLOCKSETUP
void (*blocksetup)(FAR struct sdio_dev_s *dev, unsigned int blocklen,
unsigned int nblocks);