一、错误分析

1.1 错误信息

板子从SD卡启动,Uboot阶段可以正常识别并读出内核,SD是ok的,板子的eSDHC控制器也是ok的,到了内核初始化部分报错:


sdhci-esdhc 2140000.esdhc: Adding to iommu group 4
mmc0: SDHCI controller on 2140000.esdhc [2140000.esdhc] using ADMA 64-bit

mmc0: error -110 whilst initialising SD card

1.2 驱动添加打印跟踪

drivers/mmc/core/sd.c,省略不相关代码,mmc_sd_init_card()执行错误。


/*
 * Starting point for SD card init.
 */
int mmc_attach_sd(struct mmc_host *host)
{
    int err;
    u32 ocr, rocr;

    WARN_ON(!host->claimed);

    ...
    /*
     * Detect and init the card.
     */
    err = mmc_sd_init_card(host, rocr, NULL);
    if (err)
        goto err;
    ...
err:
    mmc_detach_bus(host);

    pr_err("%s: error %d whilst initialising SD card\n",
        mmc_hostname(host), err);

    return err;
}


mmc_sd_get_cid(),获取能力出错。


/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
    struct mmc_card *oldcard)
{
    struct mmc_card *card;
    int err;
    u32 cid[4];
    u32 rocr = 0;
    bool v18_fixup_failed = false;

    WARN_ON(!host->claimed);
retry:
    err = mmc_sd_get_cid(host, ocr, cid, &rocr);
    if (err)
        return err;

    ...

}


/*
 * Fetch CID from card.
 */
int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
{
    int err;
    u32 max_current;
    int retries = 10;
    u32 pocr = ocr;

try_again:
    if (!retries) {
        ocr &= ~SD_OCR_S18R;
        pr_warn("%s: Skipping voltage switch\n", mmc_hostname(host));
    }

    /*
     * Since we're changing the OCR value, we seem to
     * need to tell some cards to go back to the idle
     * state.  We wait 1ms to give cards time to
     * respond.
     */
    mmc_go_idle(host);

    /*
     * If SD_SEND_IF_COND indicates an SD 2.0
     * compliant card and we should set bit 30
     * of the ocr to indicate that we can handle
     * block-addressed SDHC cards.
     */
    err = mmc_send_if_cond(host, ocr);
    if (!err)
        ocr |= SD_OCR_CCS;

    /*
     * If the host supports one of UHS-I modes, request the card
     * to switch to 1.8V signaling level. If the card has failed
     * repeatedly to switch however, skip this.
     */
    if (retries && mmc_host_uhs(host))
        ocr |= SD_OCR_S18R;

    /*
     * If the host can supply more than 150mA at current voltage,
     * XPC should be set to 1.
     */
    max_current = sd_get_host_max_current(host);
    if (max_current > 150)
        ocr |= SD_OCR_XPC;

    //第一次执行mmc_send_app_op_cond没有问题:ocr = 0x41200000, *rocr = 0xc1ff8000

    //第二次执行出了问题,超时
    err = mmc_send_app_op_cond(host, ocr, rocr);
    if (err)
        return err;

    /*
     * In case CCS and S18A in the response is set, start Signal Voltage
     * Switch procedure. SPI mode doesn't support CMD11.
     */
    if (!mmc_host_is_spi(host) && rocr &&
       ((*rocr & 0x41000000) == 0x41000000)) {  //第一次执行完mmc_send_app_op_cond后,*rcor的bit30 CCS 和bit24 S18A置位
        err = mmc_set_uhs_voltage(host, pocr);
        if (err == -EAGAIN) {

            /*

             * mmc_set_uhs_voltage()函数返回了-EAGAIN,进去跟踪后,发现,host设置电压信号没问题,但是检测到sd卡的四个数据位都是低电平,表示sd卡切换电压失败

             */
            retries--;
            goto try_again;
        } else if (err) {
            retries = 0;
            goto try_again;
        }
    }

    err = mmc_send_cid(host, cid);
    return err;
}

1.3 分析

问题找到了,由于SDHC控制器支持1.8V电平,初始化SD卡时,得知SD也支持1.8V操作,所以像其发送切换电压的命令,但是切换失败。再次尝试初始化时,已不能从SD卡正确获取信息,命令执行超时。

根本原因:SDHC控制器和SD卡座之间添加了电平转换芯片,SDHC的工作电压为1.8V,SD卡座的工作电压为3.3V,SD卡切换为1.8V操作模式时,肯定无法正常工作,因为外部电压是3.3V。

二、解决

参考文档Documentation/devicetree/bindings/mmc/mmc-controller.yaml,在SDHC控制在设备树节点中添加属性no-1-8-v,如下:


  no-1-8-v:
    $ref: /schemas/types.yaml#/definitions/flag
    description:
      When specified, denotes that 1.8V card voltage is not supported
      on this system, even if the controller claims it.


&esdhc0 {
    sd-uhs-sdr104;
    sd-uhs-sdr50;
    sd-uhs-sdr25;
    sd-uhs-sdr12;
    no-1-8-v;
    status = "okay";
};

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐