您的位置:首页 > 运维架构 > Linux

Linux SD卡驱动开发(五) —— SD 卡驱动分析Core补充篇

2016-06-21 13:57 399 查看
Core层中有两个重要函数 mmc_alloc_host 用于构造host,前面已经学习过,这里不再阐述;另一个就是 mmc_add_host,用于注册host

前面探测函数s3cmci_probe,现在就来回顾一下这个函数的作用。先简要的概括一下这个函数的功能:

1、s3cmci_probe 最重要的作用是host 的注册,那么首先必须构造出一个host,这个host就是通过s3cmci_alloc_host函数来构造出来的,它是一个struct s3cmci_host类型的结构体。同时,也通过mmc_alloc_host函数构造了一个struct mmc_host的结构体变量mmc。

2、初始化host的时钟,设置host的gpio等等其他一些“乱七八糟”的参数初始化(前面分析过)。

3、通过s3cmci_add_host函数来注册host。

下面是这个函数的详细分析

mmc_add_host [core/host.c]

[cpp] view
plain copy







/**

* mmc_add_host - initialise host hardware

* @host: mmc host

*

* Register the host with the driver model. The host must be

* prepared to start servicing requests before this function

* completes.

*/

int mmc_add_host(struct mmc_host *host)

{

int err;

WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&

!host->ops->enable_sdio_irq);

err = device_add(&host->class_dev);

if (err)

return err;

led_trigger_register_simple(dev_name(&host->class_dev), &host->led);

#ifdef CONFIG_DEBUG_FS

mmc_add_host_debugfs(host);

#endif

mmc_host_clk_sysfs_init(host);

mmc_start_host(host);

register_pm_notifier(&host->pm_notify);

return 0;

}

我们看一下mmc_add_host这个函数,它的功能就是通过device_add函数将设备注册进linux设备模型,最终的结果就是在sys/bus/platform/devices目录下能见到s3c-sdhci.1,s3c-sdhci.2,s3c-sdhci.3设备节点。

重点是mmc_start_host(host);这也是core层的函数具体的方法如下:

mmc_start_host [core/core.c]

[cpp] view
plain copy







void mmc_start_host(struct mmc_host *host)

{

host->f_init = max(freqs[0], host->f_min);

host->rescan_disable = 0;

if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)

mmc_power_off(host);

else

mmc_power_up(host, host->ocr_avail);

_mmc_detect_change(host, 0, false);

}

首先来看一下mmc_power_off,内容如下:

[core/core.c]

[cpp] view
plain copy







void mmc_power_off(struct mmc_host *host)

{

if (host->ios.power_mode == MMC_POWER_OFF)

return;

mmc_host_clk_hold(host);

host->ios.clock = 0;

host->ios.vdd = 0;

if (!mmc_host_is_spi(host)) {

host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;

host->ios.chip_select = MMC_CS_DONTCARE;

}

host->ios.power_mode = MMC_POWER_OFF;

host->ios.bus_width = MMC_BUS_WIDTH_1;

host->ios.timing = MMC_TIMING_LEGACY;

mmc_set_ios(host);

/*

* Some configurations, such as the 802.11 SDIO card in the OLPC

* XO-1.5, require a short delay after poweroff before the card

* can be successfully turned on again.

*/

mmc_delay(1);

mmc_host_clk_release(host);

}

关心最多的就是host->iOS当中的内容,前段的赋值真正作用在硬件上是调用host层向上提供的struct
mmc_host_ops
接口。这里18行实际上就是完成了这个工作。

回到mmc_start_host,mmc_detect_change(host, 0) 看名字就知道是用来检测SD卡的,内容如下:

mmc_detect_change(host, 0)

[core/core.c]

[cpp] view
plain copy







static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,

bool cd_irq)

{

#ifdef CONFIG_MMC_DEBUG

unsigned long flags;

spin_lock_irqsave(&host->lock, flags);

WARN_ON(host->removed);

spin_unlock_irqrestore(&host->lock, flags);

#endif

/*

* If the device is configured as wakeup, we prevent a new sleep for

* 5 s to give provision for user space to consume the event.

*/

if (cd_irq && !(host->caps & MMC_CAP_NEEDS_POLL) &&

device_can_wakeup(mmc_dev(host)))

pm_wakeup_event(mmc_dev(host), 5000);

host->detect_change = 1;

mmc_schedule_delayed_work(&host->detect, delay);

}

除了20行说了句人话,其他的百分之九十九的都是废话。曾几何时我们说过内核有个延时工作队列,没错就是他了。当然这可不是随便拿来玩的,与之对应的初始化前面已经说过即INIT_DELAYED_WORK(&host->detect, mmc_rescan);好了20 行作用的结果估计大家都能猜到了,就是延时delay 时间后就会去调用mmc_rescan了。前面我们传递的delay=0,那么这里就没有延时了,既然驱动都等不及要rescan了,我们也就不再卖关子了,直接mmc_rescan。它的功能就是扫描所插入的卡

这就回到了Linux SD卡驱动开发(三) —— SD 卡驱动分析CORE篇
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: