diff mbox

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

Message ID CACCg+XPNhms30GFE9fTKtgCb7uJPnb6KPhr+_gUS1VVk3RovmA@mail.gmail.com
State RFC
Headers show

Commit Message

Macpaul Lin Nov. 3, 2011, 11:56 a.m. UTC
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.

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.

Comments

Macpaul Lin Nov. 8, 2011, 9:15 a.m. UTC | #1
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!
Andy Fleming Nov. 8, 2011, 8:13 p.m. UTC | #2
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
Macpaul Lin Nov. 18, 2011, 8:51 a.m. UTC | #3
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.
diff mbox

Patch

--- 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;