高通apq 8098プラットフォームsdカードまとめ

5332 ワード

高通apq 8098プラットフォームsdカードまとめ
目次
参照リンク:https://blog.csdn.net/lsn946803746/article/details/52311654
msm8998-mtp.dtsiでは、デバイスツリーの定義は次のとおりです.
&sdhc_2 { vdd-supply = ; qcom,vdd-voltage-level = <2950000 2960000>; qcom,vdd-current-level = <200 800000>;
vdd-io-supply = ;
qcom,vdd-io-voltage-level = <1808000 2960000>;
qcom,vdd-io-current-level = <200 22000>;

pinctrl-names = "active", "sleep";
pinctrl-0 = ;
pinctrl-1 = ;

qcom,clk-rates = <400000 20000000 25000000
            50000000 100000000 200000000>;
qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";

cd-gpios = ;

status = "ok";

};
sdの挿入はgpio 95によって検出され、中断が発生し、中断処理関数および申請関数は以下の通りである.
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) {
    if (!ctx->cd_gpio_isr)
        ctx->cd_gpio_isr = mmc_gpio_cd_irqt;
    ret = devm_request_threaded_irq(host->parent, irq,
        NULL, ctx->cd_gpio_isr,
        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;

} EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);
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;

}
void mmc_detect_change(struct mmc_host *host, unsigned long delay) { _mmc_detect_change(host, delay, true); } EXPORT_SYMBOL(mmc_detect_change);
static void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq) { … mmc_schedule_delayed_work(&host->detect, delay); }
mmc_schedule_delayed_workは遅延キューをスケジューリングするcoreです.c実現した.つまり、sd cardの挿抜が中断をトリガーし、遅延ワークキューに参加するworkqueueは最初から初期化され、workqueue=alloc_ordered_workqueue(“kmmcd”, 0); 初期化時、sdhci-msm.c中static int sdhci_msm_probe(struct platform_device *pdev) { … host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata, 0); … ret = sdhci_add_host(host); } sdhci-pltfm.cのstruct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, const struct sdhci_pltfm_data *pdata, size_t priv_size) { … host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pltfm_host) + priv_size); }
struct sdhci_host *sdhci_alloc_host(struct device *dev, size_t priv_size) { … mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); }
struct mmc_host *mmc_alloc_host(int extra, struct device *dev) { int err; struct mmc_host *host;
host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
if (!host)
	return NULL;

/* scanning will be enabled when we're ready */
host->rescan_disable = 1;
idr_preload(GFP_KERNEL);
spin_lock(&mmc_host_lock);
err = idr_alloc(&mmc_host_idr, host, 0, 0, GFP_NOWAIT);
if (err >= 0)
	host->index = err;
spin_unlock(&mmc_host_lock);
idr_preload_end();
if (err < 0) {
	kfree(host);
	return NULL;
}

dev_set_name(&host->class_dev, "mmc%d", host->index);

host->parent = dev;
host->class_dev.parent = dev;
host->class_dev.class = &mmc_host_class;
device_initialize(&host->class_dev);

if (mmc_gpio_alloc(host)) {
	put_device(&host->class_dev);
	return NULL;
}

mmc_host_clk_init(host);

spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan);

#ifdef CONFIG_PM host->pm_notify.notifier_call = mmc_pm_notify; #endif setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host);
/*
 * By default, hosts do not support SGIO or large requests.
 * They have to set these according to their abilities.
 */
host->max_segs = 1;
host->max_seg_size = PAGE_CACHE_SIZE;

host->max_req_size = PAGE_CACHE_SIZE;
host->max_blk_size = 512;
host->max_blk_count = PAGE_CACHE_SIZE / 512;

return host;

}
void mmc_rescan(struct work_struct *work) { … mmc_rescan_try_freq(host, host->f_min); }
int sdhci_add_host(struct sdhci_host *host) { … ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, IRQF_SHARED, mmc_hostname(mmc), host); }
kernelレイヤがsdカード挿入イベントを報告するプロセスは、sdhci_thread_irq—>mmc_detect_change—>_mmc_detect_change—>mmc_schedule_delayed_work—>mmc_rescan—>mmc_rescan_try_freq() —>mmc_attach_sd—>mmc_add_card—>device_add
kernelレイヤがsdカードの抜去イベントを報告するプロセスは、sdhci_thread_irq—>mmc_detect_change—>_mmc_detect_change—>mmc_schedule_delayed_work—>mmc_rescan—>mmc_sd_detect—>mmc_remove_card—>device_del