iMX6 uSDHC and eMMC

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

iMX6 uSDHC and eMMC

Jump to solution
4,251 Views
ogj
Contributor IV

 

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:

ogj_0-1617773247891.png

 

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?

Labels (1)
Tags (1)
0 Kudos
Reply
1 Solution
4,205 Views
ogj
Contributor IV

My bad - didn't read the TRM closely. When setting up the IOMUXC for the data pins I thought the pin muxes for port SDHC4 would be ALT_FUNC_0 like the other SDHC ports. Turns out they should be ALT_FUNC_1. Thanks for your help. Everything works now.

View solution in original post

0 Kudos
Reply
6 Replies
4,227 Views
BiyongSUN
NXP Employee
NXP Employee

Why  CMD8 for emmc in JEDEC spec should be the same CMD8 in SD Card association spec?

0 Kudos
Reply
4,244 Views
igorpadykov
NXP Employee
NXP Employee

Hi Ken

 

one can test other emmc parts/boards as this particular emmc can be broken.

Also one can check procedure on i.MX6Q Sabre SD board. May be useful below link

where some emmc parts work and some not:

https://community.nxp.com/t5/i-MX-Processors/eMMC-8GB-to-4GB-crash-on-linux-yocto-boot/m-p/373231

 

Best regards
igor

0 Kudos
Reply
4,238 Views
ogj
Contributor IV

The board came preloaded with uboot and linix on the eMMC and it does run.

0 Kudos
Reply
4,220 Views
igorpadykov
NXP Employee
NXP Employee

>The board came preloaded with uboot and linix on the eMMC and it does run.

 

in such case you can debug it and compare procedure steps with failing case.

 

Best regards
igor

0 Kudos
Reply
4,206 Views
ogj
Contributor IV

My bad - didn't read the TRM closely. When setting up the IOMUXC for the data pins I thought the pin muxes for port SDHC4 would be ALT_FUNC_0 like the other SDHC ports. Turns out they should be ALT_FUNC_1. Thanks for your help. Everything works now.

0 Kudos
Reply
4,213 Views
BiyongSUN
NXP Employee
NXP Employee

Please search the SD association spec to check if you can find the extended CSD in SD association spec,  which is in the eMMC JEDEC spec. They are two different specs. 

0 Kudos
Reply