RZ/G2M Hangs when booting some SD cards

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I have a small collection of microSD cards that appear to hang when
booting.  It affects Renesas' 4.19 CIP kernel as well as 5.18.0-rc2
with the following:

[    2.717601] mmc1: tuning execution failed: -5
[    2.721979] mmc1: error -5 whilst initialising SD card
[    2.839001] mmc1: tuning execution failed: -5
[    2.843378] mmc1: error -5 whilst initialising SD card

I can use these same cards on a different platform like NXP IXM8M, and
they enumerate and mount just fine on a Linux machine, and my boot
vFAT partition mounts just fine on a Windows machine, so it seems
limited to just Renesas on Linux.

I did some testing, and I found that U-Boot on the same board can also
properly initialize the microSD card and it emuerates at sdr104.

Manufacturer ID: 1d
OEM: 4144
Name: USDBus Speed: 199999992
Mode: UHS SDR104 (208MHz)
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 29.8 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes
=>

This lead me to believe that U-Boot is initializing the micro SD card
differently than Linux, so I investigated the drivers in both to
compare what's happening differently.

The drivers between U-Boot [1] and Linux [2] appear very similar to
each other, but I noticed that U-Boot does something that Linux does
not do.

In U-Boot, renesas_sdhi_select_tuning checks a series of bits in
priv->smcmp and clears them.

renesas_sdhi_select_tuning()
<snip>

for (i = 0; i < priv->tap_num * 2; i++) {
    if (!(taps & BIT(i))) {
        taps &= ~BIT(i % priv->tap_num);
        taps &= ~BIT((i % priv->tap_num) + priv->tap_num);
    }
    if (!(priv->smpcmp & BIT(i))) {
        priv->smpcmp &= ~BIT(i % priv->tap_num);
        priv->smpcmp &= ~BIT((i % priv->tap_num) + priv->tap_num);
    }
}

Later in the code, it checks to see if various bits in priv->smcmp are set

for (i = 0; i < priv->tap_num * 2; i++) {
    if (priv->smpcmp & BIT(i))
        ntap++;
    else {
        if (ntap > match_cnt) {
            tap_start = i - ntap;
            tap_end = i - 1;
            match_cnt = ntap;
        }

<snip>

In Linux, the driver is split into multiple parts, so it's a little
harder to follow, but it appears to do something similar in
renesas_sdhi_select_tuning where it checks bits and clears various
bits in priv-smpcmp:

for (i = 0; i < taps_size; i++) {
    int offset = priv->tap_num * (i < priv->tap_num ? 1 : -1);

    if (!test_bit(i, priv->taps))
        clear_bit(i + offset, priv->taps);

    if (!test_bit(i, priv->smpcmp))
        clear_bit(i + offset, priv->smpcmp);
}

So far, these look fairly similar.

However,  a bit later, the code that checks the smcmp in U-Boot
appears dramatically different in Linux, and I don't understand the
tuning phase nor do  I have the sd card spec.

In U-BOot there is a comment (with some corresponding code) that states:

/*
* Find the longest consecutive run of successful probes.  If that
* is more than RENESAS_SDHI_MAX_TAP probes long then use the
* center index as the tap.
*/

This chunk of code appears drastically different from the Linux side,
but maybe it's ok.

Then later, U-Boot has a for loop which either increases the ntap if
priv->smpcmp & BIT(it) is set or does some math on adjusting
tap_start, end and match_cnt.  It's covered by a comment that reads:

/*
* If all of the TAP is OK, the sampling clock position is selected by
* identifying the change point of data.
*/

I don't understand the logic on the Linux side, but when we get down a
bit further, we end with

if (tap_cnt >= min_tap_row)
    priv->tap_set = (tap_start + tap_end) / 2 % priv->tap_num;
else
    return -EIO;

Which I believe yields the failure  of

"error -5 whilst initialising SD card" that I mentioned above.

I was thinking about taking the math from the U-Boot and porting it to
Linux to see if the issue goes away, but before I did that, I was
hoping someone might have some insights to see if that's the right
direction to go.

thanks

adam

[1] - https://source.denx.de/u-boot/u-boot/-/blob/master/drivers/mmc/renesas-sdhi.c
[2] - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/mmc/host/renesas_sdhi_core.c?h=v5.18-rc2



[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux