解决:mmc0: error -110 whilst initialising SD card.md

本文分析了一种常见的SD卡初始化失败现象,详细介绍了错误发生的原因,并给出了具体的解决方案。通过在设备树中添加no-1-8-v属性,避免了SDHC控制器尝试将SD卡切换到1.8V操作模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、错误分析

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

### 回答1: 抱歉,作为一名语言模型,我无法绘制图像。但我可以为你描述一个简单的网络拓扑图,它可能类似于这样: 在中心,有一个圆形的节点,代表服务器或路由器。从该节点向外伸出几条线,每条线代表一个网络连接。每个连接的末端可能是另一个圆形节点,也可能是一个小圆点,代表计算机或其他设备。 在实际的网络拓扑图中,可能还会有更多的节点、连接和子网。但是这个简单的示例应该足以帮助你理解网络拓扑的基本概念。 ### 回答2: 网络拓扑图是一种用图形表示网络结构的工具。它展示了网络中各个节点和它们之间的连接关系。一个简单的网络拓扑图可以如下所示: 在这张图中,我们有四个节点,分别用A、B、C、D表示。这四个节点可以代表计算机、服务器或其他网络设备。这些节点之间的连接关系是通过连线表示的,箭头表示了连接的方向。 在这个例子中,A节点连接到B和C节点,B节点连接到C和D节点,C节点连接到D节点。这种连接方式可以是有线连接,比如以太网线,或者是无线连接,比如Wi-Fi。 这个简单的网络拓扑图展示了一个典型的星型拓扑结构,其中A节点是中心节点,其他节点都与它相连。这种拓扑结构通常用于小型网络,例如家庭网络或办公室网络。 通过网络拓扑图,我们可以清楚地看到网络中各个节点之间的连接关系,帮助我们理解和管理网络。此外,它还能够帮助我们确定网络中的瓶颈和故障点,以便更好地优化网络性能或解决问题。 总之,网络拓扑图是一种简单而重要的工具,可以帮助我们理解和管理网络。它可以根据实际情况进行扩展和调整,以适应更复杂的网络结构。 ### 回答3: 网络拓扑图是用于描述计算机网络中各个设备之间连接关系的图形化表示。以下是一个简单的网络拓扑图的描述: 这个网络拓扑图描述了一个小型办公室网络,其中有5台设备,包括1台路由器、2台台式电脑、1台打印机和1台无线接入点。所有设备都通过以太网连接。 在图的左侧,有一台标有“路由器”的设备,它有多个以太网接口,用于与其他设备连接。从路由器分别连接到两台台式电脑和无线接入点。无线接入点放置在办公室中心,它通过无线信号与其他无线设备通信。 两台台式电脑位于网络中间部分,它们分别通过以太网电缆与路由器相连。这些电脑可以通过路由器互相通信,并与其他设备进行数据交换。 在图的右侧,有一台打印机,它通过以太网连接到路由器。这将使所有网络中的设备都能够与打印机进行通信和共享打印资源。 整个网络拓扑图简单明了,清晰地展示了设备之间的连接关系。它可以帮助人们更好地理解网络结构,诊断和解决网络问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值