[U-Boot] [RFC] [MMC] Is the HIGH_SPEED_SUPPORT bit checked wrong in mmc.c?

Hi all,
I have a problem on reading low speed card on my platform. While high speed card were all correct.
However I have only SD 1.0 specification in hand, I'll try to get 3.0 version tomorrow.
But, I've found that in include/mmc.h /* SCR definitions in different words */ #define SD_HIGHSPEED_BUSY 0x00020000 #define SD_HIGHSPEED_SUPPORTED 0x00020000 The both of these 2 defined the same value.
Then I've force the driver/mmc/mmc.c return 0 before checking SD_HIGHSPEED_SUPPORTED bit. (workaround) All operations on low speed card get correct now. The mmcinfo, fatls and fatload works normally like high speed cards.
--- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -784,6 +784,7 @@ retry_scr: }
/* If high-speed isn't supported, we return */ + return 0; if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)) return 0;
Because I have no specification in hand, I cannot check the bit fields and send correct patch if there is a problem until next week. Could someone help to check it before this weekend ?
Thanks.

Hi all,
2011/11/3 馬克泡 macpaul@gmail.com:
Hi all,
I have a problem on reading low speed card on my platform. While high speed card were all correct.
I've reported a problem with FTSDC010 controller last week. The problem is, when I'm using card SD ver 1.10 on the platform, the hardware will report CRC_FAIL when doing DATA transaction when it reads more then 1 block (512bytes).
After debugging into the problem, I found that if force the high speed card (capability) under low speed mode, the CRC_FAIL problem won't occur. But, the high speed card which is SD ver 2.0 and later won't have this kind of problem.
However, after I've got the SD 3.0 specification this week. I've checked CSD information and SD_SWITCH_SWITCH (STATUS) information with the card I've read. The detecting function of high_speed seems no problem at all. But controller still report CRC_FAIL when the hardware is doing DATA transaction. Some cards will even worse, the hardware will report CRC_FAIL on SD_SWITCH_CHECK Command.
After comparing to the Linux generic mmc stack. I've found that when the mmc stack is setting ios (clock) of the card, even if the card reported it has high speed capability (SW_SWITCH_STATUS >50Mhz), the mmc stack will still check the tran_speed (CSD) recorded in mmc card. However, the u-boot's mmc stack will only check if the clock is smaller than f_max (this should be the capability of mmc host controller, correct?) but not the actual speed of the card.
The following is the part of Linux code, "drivers/mmc/core/sd.c", mmc_sd_init_card(). /* * Compute bus speed. */ max_dtr = (unsigned int)-1;
if (mmc_card_highspeed(card)) { if (max_dtr > card->sw_caps.hs_max_dtr) { max_dtr = card->sw_caps.hs_max_dtr; printk(KERN_WARNING "%s: sw_caps.hs_max_dtr compute bus speed: %08x\n", __func__, card->sw_caps.hs_max_dtr);
} } else if (max_dtr > card->csd.max_dtr) { max_dtr = card->csd.max_dtr; printk(KERN_WARNING "%s: csd.max_dtr compute bus speed: %08x\n", __func__, card->csd.max_dtr);
}
mmc_set_clock(host, max_dtr);
The following is the u-boot code, "drivers/mmc/mmc.c", mmc_startup(). if (IS_SD(mmc)) {
[snip]
if (mmc->card_caps & MMC_MODE_HS) mmc_set_clock(mmc, 50000000); else { mmc_set_clock(mmc, 25000000);
The stack will set 50Mhz as the value of the clock to the driver if MMC_MODE_HS has been detected. The MODE_HS detecting function are most the same in both Linux's and u-boot's code.
In my case, the capability of the platform can support clock up to 33000000MHz, which is depended to the AHBBUS_CLOCK.
I'm going to add a piece of code to like the behavior in the Linux. Please help on comments. Thanks!

On Tue, Nov 8, 2011 at 3:15 AM, Macpaul Lin macpaul@gmail.com wrote:
Hi all,
[...]
I'm going to add a piece of code to like the behavior in the Linux. Please help on comments. Thanks!
That sounds good to me.
Andy

Hi Andy,
2011/11/9 Andy Fleming afleming@gmail.com:
On Tue, Nov 8, 2011 at 3:15 AM, Macpaul Lin macpaul@gmail.com wrote:
Hi all,
[...]
That sounds good to me.
Andy
if (mmc->card_caps & MMC_MODE_HS) mmc_set_clock(mmc, 50000000); else mmc_set_clock(mmc, 25000000);
On my platform, I found the frequency related to HIGHSPEED to be set with mmc_set_clock seem not related to if the card really switched to high speed mode. It is weird but it looks works fine if I forced the card in low speed but set 50MHz to controller.
The only problem I've found is if the host doesn't afford HIGHSPEED capability even the card dose, the mmc should not send SD_SWITCH command to card to make the card switch to high speed. Under this circumstance, the host and the card will run in different mode then lead problem when data transaction even the host could provide 50MHz.
I've send the fix patch "mmc: add host_caps checking avoid switch card improperly" to avoid this problem. http://patchwork.ozlabs.org/patch/126164/
I also send a patch about new fix (PATCH v3) of the ftsdc010 controller to force the host capability. http://patchwork.ozlabs.org/patch/126166/
I think this is enough for the RFC because I cannot reproduce the problem related to clock misconfiguration (25MHz, 50MHz) with my environment.
Thanks.
participants (3)
-
Andy Fleming
-
Macpaul Lin
-
馬克泡