I’m having trouble getting the usdhc controller in the iMX6Q working with the onboard Micron MTFC4GACAJCN-4M eMMC device. Our driver works fine with SDHC cards (on SDHC2 and SDHC3). SDHC4 is connected to an eMMC device. We realize that some commands are different between SD cards and eMMC devices. The board is an OTS iMX6 Quad from Embedded Artists.
The issue is with sending CMD8 to get the extended CSD – it fails. The following commands are executed successfully before sending the CMD8: CMD0, CMD1, CMD2, CMD3, at this point the operating frequency is changed to 26 MHz per the iMX6 SDK, CMD9, CMD7 (eMMC does go to trans state), CMD6 to change to 8-bit bus, CMD16 ( 512 byte sectors – necessary??), and then CMD8.
On sending CMD8, the command is accepted (INTSTAT bit 0 is a 1), but no data transfers. We’ve tried the SDK code (PIO mode to double check) and our own code which uses DMA, but no data transfers. Here are the registers (SDK PIO mode) while waiting for data to transfer:

Note that INTSTAT is 1 (command complete), but PRSSTAT bit BREN is low meaning no data is available to read. CDIHB is high indicating transfer in progress. RTA is high indicating a data read is active. BLK_ATT shows 1 block of 512 bytes. Should SDOFF be high at this point or does that matter?
Here is the code for setting up the read:
static int32_t mmc_read_esd
(
SDHC_MemMapPtr reg_ptr
)
{
CMD cmd;
// Set block length
card_cmd_config(&cmd, CMD16, BLK_LEN, READ, RESPONSE_48, DATA_PRESENT_NONE, TRUE, TRUE);
usdhc_printf("Sending CMD16\n");
// Send CMD16
if(SUCCESS == host_send_cmd(reg_ptr, &cmd))
{
// Configure block attribute
host_cfg_block(reg_ptr, BLK_LEN, ONE, ESDHC_BLKATTR_WML_BLOCK);
// Read extended CSD
card_cmd_config(&cmd, CMD8, NO_ARG, READ, RESPONSE_48, DATA_PRESENT, TRUE, TRUE);
usdhc_printf("Sending CMD8\n");
// Send CMD8
if(SUCCESS == host_send_cmd(reg_ptr, &cmd))
{
return host_data_read(reg_ptr, (uint32_t *) ext_csd_data, BLK_LEN, ESDHC_BLKATTR_WML_BLOCK);
}
}
return(FAIL);
}
The command is accepted, and here’s the code for reading the buffer (which is the same code used to read CMD17/18 data for an SD card which works fine):
int32_t host_data_read
(
SDHC_MemMapPtr reg_ptr,
uint32_t *dst_ptr,
uint32_t length,
uint32_t wml
)
{
int32_t idx;
int32_t itr;
uint32_t loop;
// Enable Interrupt flags
reg_ptr->IRQSTATEN |= ESDHC_INTERRUPT_ENABLE;
// HW_USDHC_INT_STATUS_EN(instance).U |= ESDHC_INTERRUPT_ENABLE;
// Read data to dst_ptr
loop = length / (4 * wml); //wml is in 32-bit words - length is in bytes
for(idx = 0; idx < loop; idx++)
{
// Wait until buffer ready
while(!(reg_ptr->PRSSTAT & SDHC_PRSSTAT_BREN));
// Read from FIFO watermark words
for(itr = 0; itr < wml; itr++)
{
*dst_ptr = reg_ptr->DATPORT;
dst_ptr++;
}
}
// Read leftover data that is not WML aligned
// Note: loop is used here as the number of words left to read
loop = (length % (4 * wml)) / 4;
if(loop != 0)
{
// Wait until buffer ready
while(!(reg_ptr->PRSSTAT & SDHC_PRSSTAT_BREN));
// Read the leftover to destination buffer
for(itr = 0; itr < loop; itr++)
{
*dst_ptr = reg_ptr->DATPORT;
dst_ptr++;
}
Reading stalls waiting for the SDHC_PRSSTAT_BREN bit to be set – which never happens. This is using the SDK code.
Any ideas?