i.MX6q SDIO error by large size data read

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

i.MX6q SDIO error by large size data read

Jump to solution
5,025 Views
kotayonezawa
Contributor II

Hello community.

Now we are using i.MX6 quad SABRE AUTO board and faced a problem on SDIO.
About software, Linux for i.MX (4.1.15-1.2.0) is used.

We are using device IC that has 4bit SDIO version 2.00 slave interface to read large data,
so we are now trying it on SABRE board.
We used CMD53(IO_RW_EXTENDED) with OP Code = 0 (means fixed address).
The register address was 0x10000 in SDIO register address space.
The block size was 2048 because we considered it's best setting for i.MX6 host
according to Linux source code.

So, we started implementation but faced strange phenomenon.

  - If the total read data size is less than 64KB (65536byte), sdio_readsb() function

    on Linux (CMD53 function with OP Code = 0) finished successfully.
  - If the total read data size is greater than or equal to 64KB,

    sdio_readsb() function failed. The return code was -ETIMEDOUT (-110).

    In dmesg, we found following message.
    "mmc0: Timeout waiting for hardware interrupt."
    From above message, it seems that sdhci_timeout_timer() in sdhci.c failed by ETIMEDOUT.

We changed block size to smaller, but the phenomenon was same.

We understood that if CMD53(IO_RW_EXTENDED) with OP Code = 1 (means incrementing address)
we'll face similar issue because SDIO address space is 17bit. (0x10000 - 0x1FFFFF is 64KB)
But we are now using OP Code = 0. (fixed address)
So we are now confused and need help.

Of course, we suspected at first that our device IC was not OK,
but same IC was used with "Panda Board" via SDIO interface before, and we've never faced such issue.
Over 64KB large size data can be read from the IC on "Panda Board" environment.

Our question is, if i.MX6q SDIO host has some limitation on CMD53 data size
or block count on OP Code = 0, we would like to know about it.
Did someone face or know similar issue?

Best Regards,
Yonezawa

Labels (2)
Tags (3)
1 Solution
3,334 Views
kotayonezawa
Contributor II

Hi igor, all,

Thanks a lot for your reply.

It seems that we found root cause.

As the document you suggested:

sect.1.13.3 Data Address and Data Length Requirements p.15 SD specification
https://members.sdcard.org/downloads/pls/simplified_specs/archive/partA2_300.pdf

The i.MX host controller does NOT allow 64KB data size for each descriptor.

In Linux code, following quirk flag seems to be used for this spec.

(in sdhci.h)

/* Controller treats ADMA descriptors with length 0000h incorrectly */
#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30)

This quirk flag is set in sdhci-esdhc-imx.c.

static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
    .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT
        | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
        | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC
        | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
    .ops = &sdhci_esdhc_ops,
};

We are not so sure but in newer SD spec, length = 0 setting seems to be accepted, correct??

Anyway, if this quirk flag is set, the max_seg_size member in struct mmc_host is set to 65535 in sdhci.c.

    /*
    * Maximum segment size. Could be one segment with the maximum number
    * of bytes. When doing hardware scatter/gather, each entry cannot
    * be larger than 64 KiB though.
    */
    if (host->flags & SDHCI_USE_ADMA) {
        if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC)
            mmc->max_seg_size = 65535;
        else
            mmc->max_seg_size = 65536;
    } else {
        mmc->max_seg_size = mmc->max_req_size;
    }

 

max_seg_size member is used in mmc_io_rw_extended function in sdio_ops.c.

We are not so sure about following code but it seems that the transfer data is split by max_seg_size.

int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
    unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
{
    struct mmc_request mrq = {NULL};
    struct mmc_command cmd = {0};
    struct mmc_data data = {0};
    struct scatterlist sg, *sg_ptr;
    struct sg_table sgtable;
    unsigned int nents, left_size, i;
    unsigned int seg_size = card->host->max_seg_size;
...

    nents = (left_size - 1) / seg_size + 1;
    if (nents > 1) {
        if (sg_alloc_table(&sgtable, nents, GFP_KERNEL))
            return -ENOMEM;

        data.sg = sgtable.sgl;
        data.sg_len = nents;

        for_each_sg(data.sg, sg_ptr, data.sg_len, i) {
            sg_set_page(sg_ptr, virt_to_page(buf + (i * seg_size)),
                min(seg_size, left_size),
                offset_in_page(buf + (i * seg_size)));
            left_size = left_size - seg_size;
        }
    } else {

We supposed that for DMA transfer, such unaligned odd number is not OK, so we tested to change max_seg_size from 65535(0xFFFF) to 61440(0xF000).

After all, the ETIMEDOUT is not occurred and the transfer seems to become OK now.

So we assumed that wrong max_seq_size setting 65535 = 0xFFFF is the root cause.

We are not so professional about SD Host, but we think that i.MX SD Host cannot accept 64KB length data for each descriptor (SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC should be set), the max_seg_size should be set correct,  and aligned value (like 0xF000) for i.MX system, we supposed.

We are not sure which code (sdhci.c or sdhci-esdhc-imx.c) should be fixed, but it's better to modify Linux SD host code to avoid similar issue.

What do you think?

Best Regards,

Yonezawa

View solution in original post

6 Replies
3,334 Views
kotayonezawa
Contributor II

Hi igor,

Thanks a lot.

We believe this fix will be useful, so please take it into consideration.

Best Regards,

Yonezawa

0 Kudos
3,335 Views
kotayonezawa
Contributor II

Hi igor, all,

Thanks a lot for your reply.

It seems that we found root cause.

As the document you suggested:

sect.1.13.3 Data Address and Data Length Requirements p.15 SD specification
https://members.sdcard.org/downloads/pls/simplified_specs/archive/partA2_300.pdf

The i.MX host controller does NOT allow 64KB data size for each descriptor.

In Linux code, following quirk flag seems to be used for this spec.

(in sdhci.h)

/* Controller treats ADMA descriptors with length 0000h incorrectly */
#define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1<<30)

This quirk flag is set in sdhci-esdhc-imx.c.

static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
    .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_HISPD_BIT
        | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
        | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC
        | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
    .ops = &sdhci_esdhc_ops,
};

We are not so sure but in newer SD spec, length = 0 setting seems to be accepted, correct??

Anyway, if this quirk flag is set, the max_seg_size member in struct mmc_host is set to 65535 in sdhci.c.

    /*
    * Maximum segment size. Could be one segment with the maximum number
    * of bytes. When doing hardware scatter/gather, each entry cannot
    * be larger than 64 KiB though.
    */
    if (host->flags & SDHCI_USE_ADMA) {
        if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC)
            mmc->max_seg_size = 65535;
        else
            mmc->max_seg_size = 65536;
    } else {
        mmc->max_seg_size = mmc->max_req_size;
    }

 

max_seg_size member is used in mmc_io_rw_extended function in sdio_ops.c.

We are not so sure about following code but it seems that the transfer data is split by max_seg_size.

int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
    unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
{
    struct mmc_request mrq = {NULL};
    struct mmc_command cmd = {0};
    struct mmc_data data = {0};
    struct scatterlist sg, *sg_ptr;
    struct sg_table sgtable;
    unsigned int nents, left_size, i;
    unsigned int seg_size = card->host->max_seg_size;
...

    nents = (left_size - 1) / seg_size + 1;
    if (nents > 1) {
        if (sg_alloc_table(&sgtable, nents, GFP_KERNEL))
            return -ENOMEM;

        data.sg = sgtable.sgl;
        data.sg_len = nents;

        for_each_sg(data.sg, sg_ptr, data.sg_len, i) {
            sg_set_page(sg_ptr, virt_to_page(buf + (i * seg_size)),
                min(seg_size, left_size),
                offset_in_page(buf + (i * seg_size)));
            left_size = left_size - seg_size;
        }
    } else {

We supposed that for DMA transfer, such unaligned odd number is not OK, so we tested to change max_seg_size from 65535(0xFFFF) to 61440(0xF000).

After all, the ETIMEDOUT is not occurred and the transfer seems to become OK now.

So we assumed that wrong max_seq_size setting 65535 = 0xFFFF is the root cause.

We are not so professional about SD Host, but we think that i.MX SD Host cannot accept 64KB length data for each descriptor (SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC should be set), the max_seg_size should be set correct,  and aligned value (like 0xF000) for i.MX system, we supposed.

We are not sure which code (sdhci.c or sdhci-esdhc-imx.c) should be fixed, but it's better to modify Linux SD host code to avoid similar issue.

What do you think?

Best Regards,

Yonezawa

3,334 Views
igorpadykov
NXP Employee
NXP Employee

Hi Yonezawa

sd driver structure is described in Table 32-5. uSDHC Driver Files MMC/SD Driver Files

attached Linux Manual. I believe it may be posted on kernel mail list or meta-fsl-arm mailing list
https://lists.yoctoproject.org/listinfo/meta-freescale

Best regards
igor

0 Kudos
3,334 Views
kotayonezawa
Contributor II

Hi igor,

Thanks a lot for your reply.
I checked documents that you refered, but I could not find the reason
that why TOTAL transfer data size of CMD53 was limited only 64KB max.

sect.67.4.1.4 Dividing Large Data Transfer i.MX6DQ Reference Manual
http://cache.nxp.com/files/soft_dev_tools/doc/support_info/iMX6DQPRM.pdf

says the total transfer data size should be multiple of block size.

Total transfer data size limitation is not described...

sect.1.13.3 Data Address and Data Length Requirements p.15 SD specification
https://members.sdcard.org/downloads/pls/simplified_specs/archive/partA2_300.pdf

describes about how to control SDIO Host ADMA.

I was interested in following description:

The maximum data length of each descriptor line is less than 64KB.

We are not so sure about SDIO Host but if the Host ADMA is not controlled correctly and set descriptor data size more than 64KB, the ADMA will be failed, right?

Anyway, additional information will be very helpful for us...

Best Regards,

Yonezawa

0 Kudos
3,334 Views
igorpadykov
NXP Employee
NXP Employee

Hi Kota

>The maximum data length of each descriptor line is less than 64KB.

this is requirement of sd specifications, not i.MX6 host controller

I believe it may be debugged using attached Linux Manual Chapter 32
MMC/SD/SDIO Host Driver

Best regards
igor

0 Kudos
3,334 Views
igorpadykov
NXP Employee
NXP Employee

Hi Kota

issue may be caused by  requirements described in
sect.67.4.1.4 Dividing Large Data Transfer i.MX6DQ Reference Manual
http://cache.nxp.com/files/soft_dev_tools/doc/support_info/iMX6DQPRM.pdf
and sect.1.13.3 Data Address and Data Length Requirements p.15 SD specification
https://members.sdcard.org/downloads/pls/simplified_specs/archive/partA2_300.pdf

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos