TF卡不能检卡问题排查
bring up阶段SD始终不能检卡,我觉得软件配置应该没问题,硬件是外包的,硬件答复这套设计其他厂商也在用没问题。SD一个卡槽,SIM一个卡槽,高通平台,Linux内核版本3.18。
先看下内核文档关于检卡的描述:
Card detection:
If no property below is supplied, host native card detect is used.
Only one of the properties in this section should be supplied:
- broken-cd: There is no card detection available; polling must be used.
- cd-gpios: Specify GPIOs for card detection, see gpio binding
- non-removable: non-removable slot (like eMMC); assume always present.
再看下dts配置:
&sdhc_2 {
#address-cells = <0>;
interrupt-parent = <&sdhc_2>;
interrupts = <0 1 2>;
#interrupt-cells = <1>;
interrupt-map-mask = <0xffffffff>;
interrupt-map = <0 &intc 0 125 0
1 &intc 0 221 0
2 &msm_gpio 38 0>;
interrupt-names = "hc_irq", "pwr_irq", "status_irq";
cd-gpios = <&msm_gpio 38 0x1>; //0x1 - 表示插卡低有效
这里用的就是gpio中断检卡方式不能工作,解析cd-gpios在sdhci_msm_populate_pdata
:
enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW; //is 1
...
pdata->status_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &flags);
if (gpio_is_valid(pdata->status_gpio) & !(flags & OF_GPIO_ACTIVE_LOW))
pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
把cd-gpios去掉就是用host native方式插拔检测正常,这种是轮训方式,sdhci_add_host
里有:
/*
* Enable polling on when card detection is broken and no card detect
* gpio is present.
*/
if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
!(mmc->caps & MMC_CAP_NONREMOVABLE) &&
(mmc_gpio_get_cd(host->mmc) < 0) &&
!(mmc->caps2 & MMC_CAP2_NONHOTPLUG))
mmc->caps |= MMC_CAP_NEEDS_POLL;
为什么用gpio中断方式不能检测呢,来看下:
中断注册在mmc_gpiod_request_cd_irq
:
void mmc_gpiod_request_cd_irq(struct mmc_host *host)
{
struct mmc_gpio *ctx = host->slot.handler_priv;
int ret, irq;
if (host->slot.cd_irq >= 0 || !ctx || !ctx->cd_gpio)
return;
irq = gpiod_to_irq(ctx->cd_gpio);
/*
* Even if gpiod_to_irq() returns a valid IRQ number, the platform might
* still prefer to poll, e.g., because that IRQ number is already used
* by another unit and cannot be shared.
*/
if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL)
irq = -EINVAL;
if (irq >= 0) {
ret = devm_request_threaded_irq(&host->class_dev, irq,
NULL, mmc_gpio_cd_irqt,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
ctx->cd_label, host);
if (ret < 0)
irq = ret;
}
host->slot.cd_irq = irq;
if (irq < 0)
host->caps |= MMC_CAP_NEEDS_POLL;
}
中断处理是mmc_gpio_cd_irqt
:
static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
{
/* Schedule a card detection after a debounce timeout */
struct mmc_host *host = dev_id;
host->trigger_card_event = true;
mmc_detect_change(host, msecs_to_jiffies(200));
return IRQ_HANDLED;
}
mmc_detect_change
会callmmc_schedule_delayed_work(&host->detect, delay);
,也就是会走mmc_rescan,因为前面有挂`INIT_DELAYED_WORK(&host->detect, mmc_rescan);
`。
sdhci_request里检卡:
/*
* Firstly check card presence from cd-gpio. The return could
* be one of the following possibilities:
* negative: cd-gpio is not available
* zero: cd-gpio is used, and card is removed
* one: cd-gpio is used, and card is present
*/
present = mmc_gpio_get_cd(host->mmc);
if (present < 0) {
/* If polling, assume that the card is always present. */
if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION)
present = 1;
else
present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
SDHCI_CARD_PRESENT;
}
注释写的很清楚,先看cd-gpio情况。
把mmc_gpio_get_cd
加入中断处理mmc_gpio_cd_irqt
中查看发现插卡时有太多的中断打印,拔出停止。
中断频繁可以看到142一直在增:
msmxxx:/ # cat /proc/interrupts | grep msmgpio
117: 11 1 1 2 msmgpio 13 msg2xxx
125: 0 0 0 0 msmgpio 21 cs35l41
142: 10651 1639 499 0 msmgpio 38 7864900.sdhci cd
GPIO配置确认:
msmxxx:/ # cat /sys/kernel/debug/gpio | grep 38
gpio38 : in 0 2mA no pull
当修改为高有效后插入中断一个,拔出中断多出几个,但是仍然不能检卡,插卡mmc_gpio_get_cd返回0,拔卡返回1。之前其他项目配置高有效时,插卡get_cd返回的都是1,拔卡返回的是0,所以应该是硬件问题,push硬件修改后果然正常了。
这类情况以前在Z就遇到过,so有时不想调dd:]
本站采用CC BY-NC-SA 4.0进行许可 | 转载请注明原文链接 - TF卡不能检卡问题排查