Add SD card initialization logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2258 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2009-11-15 18:23:46 +00:00
parent 95908c8777
commit 529bbb7a2a
4 changed files with 604 additions and 129 deletions
+111 -44
View File
@@ -123,6 +123,7 @@ static inline void stm32_dmaenable(void);
/* Data Transfer Helpers ****************************************************/
static ubyte stm32_log2(uint16 value);
static void stm32_dataconfig(uint32 timeout, uint32 dlen, uint32 dctrl);
static void stm32_datadisable(void);
@@ -135,13 +136,12 @@ static ubyte stm32_status(FAR struct sdio_dev_s *dev);
static void stm32_widebus(FAR struct sdio_dev_s *dev, boolean enable);
static void stm32_clock(FAR struct sdio_dev_s *dev,
enum sdio_clock_e rate);
static int stm32_setblocklen(FAR struct sdio_dev_s *dev, int blocklen,
int nblocks);
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 cmd, uint32 arg);
static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 arg);
static int stm32_sendsetup(FAR struct sdio_dev_s *dev, uint32 nbytes);
static int stm32_senddata(FAR struct sdio_dev_s *dev,
FAR const ubyte *buffer);
@@ -150,11 +150,12 @@ static int stm32_recvshortcrc(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *
static int stm32_recvlong(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 rlong[4]);
static int stm32_recvshort(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *rshort);
static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *rnotimpl);
static int stm32_recvsetup(FAR struct sdio_dev_s *dev, uint32 nbytes);
static int stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer);
/* EVENT handler */
static void stm32_eventenable(FAR struct sdio_dev_s *dev, ubyte eventset,
static void stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset,
boolean enable);
static ubyte stm32_eventwait(FAR struct sdio_dev_s *dev, uint32 timeout);
static ubyte stm32_events(FAR struct sdio_dev_s *dev);
@@ -194,9 +195,9 @@ struct stm32_dev_s g_mmcsd =
.status = stm32_status,
.widebus = stm32_widebus,
.clock = stm32_clock,
.setblocklen = stm32_setblocklen,
.attach = stm32_attach,
.sendcmd = stm32_sendcmd,
.sendcmd = stm32_sendcmd,
.sendsetup = stm32_sendsetup,
.senddata = stm32_senddata,
.waitresponse = stm32_waitresponse,
.recvR1 = stm32_recvshortcrc,
@@ -205,7 +206,8 @@ struct stm32_dev_s g_mmcsd =
.recvR4 = stm32_recvnotimpl,
.recvR5 = stm32_recvnotimpl,
.recvR6 = stm32_recvshortcrc,
.recvR7 = stm32_recvshort,
.recvR7 = stm32_recvshort,
.recvsetup = stm32_recvsetup,
.recvdata = stm32_recvdata,
.eventenable = stm32_eventenable,
.eventwait = stm32_eventwait,
@@ -378,6 +380,37 @@ static inline void stm32_dmaenable(void)
/****************************************************************************
* Data Transfer Helpers
****************************************************************************/
/****************************************************************************
* Name: stm32_log2
*
* Description:
* Take (approximate) log base 2 of the provided number (Only works if the
* provided number is a power of 2).
*
****************************************************************************/
static ubyte stm32_log2(uint16 value)
{
ubyte 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: stm32_dataconfig
*
@@ -490,7 +523,11 @@ static ubyte stm32_status(FAR struct sdio_dev_s *dev)
****************************************************************************/
static void stm32_widebus(FAR struct sdio_dev_s *dev, boolean wide)
{
{
if (wide)
{
priv->mode = MMCSDMODE_DMA;
}
}
/****************************************************************************
@@ -512,27 +549,6 @@ static void stm32_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
{
}
/****************************************************************************
* Name: stm32_setblocklen
*
* Description:
* Set the MMC/SD block length and block count
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* blocklen - The block length
* nblocks - The block count
*
* Returned Value:
* OK on success; negated errno on failure
*
****************************************************************************/
static int stm32_setblocklen(FAR struct sdio_dev_s *dev, int blocklen, int nblocks)
{
return -ENOSYS;
}
/****************************************************************************
* Name: stm32_attach
*
@@ -616,6 +632,31 @@ static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 arg)
putreg32(regval, STM32_SDIO_CMD);
}
/****************************************************************************
* Name: stm32_sendsetup
*
* Description:
* Setup hardware in preparation for data trasfer 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 SDIO_SENDDATA is called.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* nbytes - The number of bytes in the transfer
*
* Returned Value:
* Number of bytes sent on success; a negated errno on failure
*
****************************************************************************/
static int stm32_sendsetup(FAR struct sdio_dev_s *dev, uint32 nbytes)
{
uint32 dctrl = stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT);
stm32_dataconfig(SD_DATATIMEOUT, nbytes, dctrl);
return OK;
}
/****************************************************************************
* Name: stm32_senddata
*
@@ -627,7 +668,7 @@ static void stm32_sendcmd(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 arg)
* data - Data to be sent
*
* Returned Value:
* Number of bytes sent on succes; a negated errno on failure
* Number of bytes sent on success; a negated errno on failure
*
****************************************************************************/
@@ -918,6 +959,32 @@ static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *rno
return -ENOSYS;
}
/****************************************************************************
* Name: stm32_recvsetup
*
* Description:
* Setup hardware in preparation for data trasfer from the card. 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), ...
* and before SDIO_RECVDATA is called.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* nbytes - The number of bytes in the transfer
*
* Returned Value:
* Number of bytes sent on success; a negated errno on failure
*
****************************************************************************/
static int stm32_recvsetup(FAR struct sdio_dev_s *dev, uint32 nbytes)
{
uint32 dctrl = (stm32_log2(nbytes) << SDIO_DCTRL_DBLOCKSIZE_SHIFT)) | SDIO_DCTRL_DTDIR;
stm32_dataconfig(SD_DATATIMEOUT, nbytes, dctrl);
return OK;
}
/****************************************************************************
* Name: stm32_recvdata
*
@@ -929,7 +996,7 @@ static int stm32_recvnotimpl(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *rno
* buffer - Buffer in which to receive the data
*
* Returned Value:
* Number of bytes sent on succes; a negated errno on failure
* Number of bytes sent on success; a negated errno on failure
*
****************************************************************************/
@@ -947,16 +1014,14 @@ static int stm32_recvdata(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* eventset - A bitset of events to enable or disable (see MMCSDEVENT_*
* definitions
* enable - TRUE: enable event; FALSE: disable events
* definitions). 0=disable; 1=enable.
*
* Returned Value:
* None
*
****************************************************************************/
static void stm32_eventenable(FAR struct sdio_dev_s *dev, ubyte eventset,
boolean enable)
static void stm32_eventenable(FAR struct sdio_dev_s *dev, sdio_event_t eventset)
{
}
@@ -972,7 +1037,8 @@ static void stm32_eventenable(FAR struct sdio_dev_s *dev, ubyte eventset,
*
* Returned Value:
* Event set containing the event(s) that ended the wait. If no events the
* returned event set is zero, then the wait was terminated by the timeout.
* returned event set is zero, then the wait was terminated by the timeout.
* All events are cleared disabled after the wait concludes.
*
****************************************************************************/
@@ -986,13 +1052,14 @@ static ubyte stm32_eventwait(FAR struct sdio_dev_s *dev, uint32 timeout)
*
* Description:
* Return the current event set. This supports polling for MMC/SD (vs.
* waiting).
* waiting). Only enabled events need be reported.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* dev - An instance of the MMC/SD device interface
*
* Returned Value:
* Event set containing the current events (cleared after reading).
* Event set containing the current events (All pending events are cleared
* after reading).
*
****************************************************************************/
@@ -1062,7 +1129,7 @@ static void stm32_coherent(FAR struct sdio_dev_s *dev, FAR void *addr,
* buffer - The memory to DMA from
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
@@ -1084,7 +1151,7 @@ static int tm32_dmareadsetup(FAR struct sdio_dev_s *dev, FAR ubyte *buffer)
* buffer - The memory to DMA into
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
@@ -1106,7 +1173,7 @@ static int stm32_dmawritesetup(FAR struct sdio_dev_s *dev,
* dev - An instance of the MMC/SD device interface
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
@@ -1127,7 +1194,7 @@ static int stm32_dmastart(FAR struct sdio_dev_s *dev)
* dev - An instance of the MMC/SD device interface
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
@@ -1150,7 +1217,7 @@ static int stm32_dmastop(FAR struct sdio_dev_s *dev)
* remaining in the transfer.
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
File diff suppressed because it is too large Load Diff
+34 -6
View File
@@ -60,11 +60,21 @@
#define MMCSD_CMD8ECHO_SHIFT 0 /* Bits 0-7: Check pattern */
#define MMCSD_CMD8ECHO_MASK (0xff << MMCSD_CMD8ECHO_SHIFT)
# define MMCSD_CMD8CHECKPATTERN (0xaa << MMCSD_CMD8ECHO_SHIFT)
/* ACMD6 argument */
#define MMCSD_ACMD6_BUSWIDTH_1 (0) /* Bus width = 1-bit */
#define MMCSD_ACMD6_BUSWIDTH_4 (2) /* Bus width = 4-bit */
/* ACMD41 argument */
#define MMCD_ACMD41_VOLTAGEWINDOW 0x80100000
#define MMCD_ACMD41_HIGHCAPACITY (1 << 30)
#define MMCSD_ACMD41_VOLTAGEWINDOW 0x80100000
#define MMCSD_ACMD41_HIGHCAPACITY (1 << 30)
#define MMCSD_ACMD41_STDCAPACITY (0)
/* ACMD42 argument */
#define MMCSD_ACMD42_CD_DISCONNECT (0) /* Disconnect card detection logic */
#define MMCSD_ACMD42_CD_CONNECT (1) /* Connect card detection logic */
/* R1 Card Status bit definitions */
@@ -135,9 +145,16 @@
#define MMCSD_VDD_32_33 (1 << 20) /* VDD voltage 3.2-3.3 */
#define MMCSD_VDD_33_34 (1 << 21) /* VDD voltage 3.3-3.4 */
#define MMCSD_VDD_34_35 (1 << 22) /* VDD voltage 3.4-3.5 */
#define MMCSD_VDD_35_36 (1 << 23) /* VDD voltage 3.5-3.6 */
#define MMCSD_VDD_35_36 (1 << 23) /* VDD voltage 3.5-3.6 */
#define MMCSD_R3_HIGHCAPACITY (1 << 30) /* TRUE: Card supports block addressing */
#define MMCSD_CARD_BUSY (1 << 31) /* Card power-up busy bit */
/* SD Configuration Register (SCR) encoding */
#define MMCSD_SCR_BUSWIDTH_1BIT (1)
#define MMCSD_SCR_BUSWIDTH_2BIT (2)
#define MMCSD_SCR_BUSWIDTH_4BIT (4)
#define MMCSD_SCR_BUSWIDTH_8BIT (8)
/* Last 4 bytes of the 48-bit R7 response */
@@ -153,7 +170,7 @@
/********************************************************************************************
* Public Types
********************************************************************************************/
/* Decoded Card Identification (CID) register */
struct mmcsd_cid_s
@@ -168,7 +185,7 @@ struct mmcsd_cid_s
ubyte crc; /* 7:1 7-bit CRC7 */
/* 0:0 1-bit (not used) */
};
/* Decoded Card Specific Data (CSD) register */
struct mmcsd_csd_s
@@ -264,6 +281,17 @@ struct mmcsd_csd_s
ubyte crc; /* 7:1 CRC */
/* 0:0 Not used */
};
struct mmcsd_scr_s
{
ubyte scrversion; /* 63:60 Version of SCR structure */
ubyte sdversion; /* 59:56 SD memory card physical layer version */
ubyte erasestate; /* 55:55 Data state after erase (1 or 0) */
ubyte security; /* 54:52 SD security support */
ubyte buswidth; /* 51:48 DAT bus widthes supported */
/* 47:32 SD reserved space */
uint32 mfgdata; /* 31:0 Reserved for manufacturing data */
};
/********************************************************************************************
* Public Data
+69 -40
View File
@@ -359,25 +359,6 @@
#define SDIO_CLOCK(dev,rate) ((dev)->clock(dev,rate))
/****************************************************************************
* Name: SDIO_SETBLOCKLEN
*
* Description:
* Set the MMC/SD block length and block count
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* blocklen - The block length
* nblocks - The block count
*
* Returned Value:
* OK on success; negated errno on failure
*
****************************************************************************/
#define SDIO_SETBLOCKLEN(dev,blocklen,nblocks) \
((dev)->setblocklen(dev,blocklen,nblocks))
/****************************************************************************
* Name: SDIO_ATTACH
*
@@ -413,6 +394,26 @@
#define SDIO_SENDCMD(dev,cmd,arg) ((dev)->sendcmd(dev,cmd,arg))
/****************************************************************************
* Name: SDIO_SENDSETUP
*
* Description:
* Setup hardware in preparation for data trasfer 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 SDIO_SENDDATA is called.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* nbytes - The number of bytes in the transfer
*
* Returned Value:
* Number of bytes sent on success; a negated errno on failure
*
****************************************************************************/
#define SDIO_SENDSETUP(dev,nbytes) ((dev)->sendsetup(dev,nbytes))
/****************************************************************************
* Name: SDIO_SENDDATA
*
@@ -424,7 +425,7 @@
* data - Data to be sent
*
* Returned Value:
* Number of bytes sent on succes; a negated errno on failure
* Number of bytes sent on success; a negated errno on failure
*
****************************************************************************/
@@ -475,7 +476,28 @@
#define SDIO_RECVR4(dev,cmd,R4) ((dev)->recvR4(dev,cmd,R4)) /* 48-bit */
#define SDIO_RECVR5(dev,cmd,R5) ((dev)->recvR5(dev,cmd,R5)) /* 48-bit */
#define SDIO_RECVR6(dev,cmd,R6) ((dev)->recvR6(dev,cmd,R6)) /* 48-bit */
#define SDIO_RECVR7(dev,cmd,R7) ((dev)->recvR6(dev,cmd,R7)) /* 48-bit */
#define SDIO_RECVR7(dev,cmd,R7) ((dev)->recvR7(dev,cmd,R7)) /* 48-bit */
/****************************************************************************
* Name: SDIO_RECVSETUP
*
* Description:
* Setup hardware in preparation for data trasfer from the card. 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), ...
* and before SDIO_RECVDATA is called.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* nbytes - The number of bytes in the transfer
*
* Returned Value:
* Number of bytes sent on success; a negated errno on failure
*
****************************************************************************/
#define SDIO_RECVSETUP(dev,nbytes) ((dev)->recvsetup(dev,nbytes))
/****************************************************************************
* Name: SDIO_RECVDATA
@@ -488,7 +510,7 @@
* buffer - Buffer in which to receive the data
*
* Returned Value:
* Number of bytes sent on succes; a negated errno on failure
* Number of bytes sent on success; a negated errno on failure
*
****************************************************************************/
@@ -502,18 +524,15 @@
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* eventset - A bitset of events to enable or disable (see SDIOEVENT_*
* definitions
* enable - TRUE: enable event; FALSE: disable events
* eventset - A bitset of events to enable or disable (see MMCSDEVENT_*
* definitions). 0=disable; 1=enable.
*
* Returned Value:
* None
*
****************************************************************************/
#define SDIO_EVENTENABLE(dev,eventset) ((dev)->eventenable(dev,eventset,TRUE))
#define SDIO_EVENTDISABLE(dev,eventset) ((dev)->eventenable(dev,eventset,FALSE))
#define SDIO_EVENTDISABLEALL(dev) ((dev)->eventenable(dev,SDIOEVENT_ALLEVENTS,FALSE))
#define SDIO_EVENTENABLE(dev,eventset) ((dev)->eventenable(dev,eventset))
/****************************************************************************
* Name: SDIO_EVENTWAIT
@@ -526,8 +545,9 @@
* timeout - Maximum time in milliseconds to wait. Zero means no timeout.
*
* Returned Value:
* Event set containing the event(s) that ended the wait. If no events the
* Event set containing the event(s) that ended the wait. If no events the
* returned event set is zero, then the wait was terminated by the timeout.
* All events are cleared disabled after the wait concludes.
*
****************************************************************************/
@@ -538,13 +558,14 @@
*
* Description:
* Return the current event set. This supports polling for MMC/SD (vs.
* waiting).
* waiting). Only enabled events need be reported.
*
* Input Parameters:
* dev - An instance of the MMC/SD device interface
* dev - An instance of the MMC/SD device interface
*
* Returned Value:
* Event set containing the current events (cleared after reading).
* Event set containing the current events (All pending events are cleared
* after reading).
*
****************************************************************************/
@@ -609,7 +630,7 @@
* buffer - The memory to DMA from
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
@@ -630,7 +651,7 @@
* buffer - The memory to DMA into
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
@@ -650,7 +671,7 @@
* dev - An instance of the MMC/SD device interface
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
@@ -670,7 +691,7 @@
* dev - An instance of the MMC/SD device interface
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
@@ -692,7 +713,7 @@
* remaining in the transfer.
*
* Returned Value:
* OK on succes; a negated errno on failure
* OK on success; a negated errno on failure
*
****************************************************************************/
@@ -713,9 +734,16 @@ enum sdio_clock_e
CLOCK_SDIO_DISABLED = 0, /* Clock is disabled */
CLOCK_IDMODE, /* Initial ID mode clocking (<400KHz) */
CLOCK_MMC_TRANSFER, /* MMC normal operation clocking */
CLOCK_SD_TRANSFER /* SD normal operation clocking */
CLOCK_SD_TRANSFER_1BIT, /* SD normal operation clocking (narrow 1-bit mode) */
CLOCK_SD_TRANSFER_4BIT /* SD normal operation clocking (wide 4-bit mode) */
};
/* Event set. A ubyte is big enough to hold a set of 8-events. If more are
* needed, change this to a uint16.
*/
typedef ubyte sdio_eventset_t;
/* This structure defines the interface between the NuttX MMC/SD
* driver and the chip- or board-specific MMC/SD interface. This
* interface is only used in architectures that support SDIO
@@ -736,12 +764,12 @@ struct sdio_dev_s
ubyte (*status)(FAR struct sdio_dev_s *dev);
void (*widebus)(FAR struct sdio_dev_s *dev, boolean enable);
void (*clock)(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate);
int (*setblocklen)(FAR struct sdio_dev_s *dev, int blocklen, int nblocks);
int (*attach)(FAR struct sdio_dev_s *dev);
/* Command/Status/Data Transfer */
void (*sendcmd)(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 arg);
int (*sendsetup)(FAR struct sdio_dev_s *dev, uint32 nbytes);
int (*senddata)(FAR struct sdio_dev_s *dev, FAR const ubyte *buffer);
int (*waitresponse)(FAR struct sdio_dev_s *dev, uint32 cmd);
@@ -752,11 +780,12 @@ struct sdio_dev_s
int (*recvR5)(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *R5);
int (*recvR6)(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *R6);
int (*recvR7)(FAR struct sdio_dev_s *dev, uint32 cmd, uint32 *R7);
int (*recvsetup)(FAR struct sdio_dev_s *dev, uint32 nbytes);
int (*recvdata)(FAR struct sdio_dev_s *dev, FAR ubyte *buffer);
/* EVENT handler */
void (*eventenable)(FAR struct sdio_dev_s *dev, ubyte eventset, boolean enable);
void (*eventenable)(FAR struct sdio_dev_s *dev, sdio_eventset_t eventset);
ubyte (*eventwait)(FAR struct sdio_dev_s *dev, uint32 timeout);
ubyte (*events)(FAR struct sdio_dev_s *dev);