mmc host 之内核接口

当我们在编写mmc host驱动时,不可避免的要调用mmc_alloc_host这个内核接口,它不仅为host申请分配内存,而且会做一定的初始化,现在贴出代码:
struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
	......

	host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); //申请分配内存
	if (!host)
		return NULL;

	spin_lock(&mmc_host_lock);
	err = idr_get_new(&mmc_host_idr, host, &host->index);
	spin_unlock(&mmc_host_lock);
	if (err)
		goto free;

	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);

	mmc_host_clk_init(host);

	spin_lock_init(&host->lock);
	init_waitqueue_head(&host->wq);
	wake_lock_init(&host->detect_wake_lock, WAKE_LOCK_SUSPEND,
		kasprintf(GFP_KERNEL, "%s_detect", mmc_hostname(host)));
	INIT_DELAYED_WORK(&host->detect, mmc_rescan); //初始化delay work,这个是为了探测mmc/sd/sdio的插入的work.
#ifdef CONFIG_PM
	host->pm_notify.notifier_call = mmc_pm_notify;
#endif

	/*
	 * 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;

free:
	kfree(host);
	return NULL;
}

然后当我们初始化完成mmc host之后,就需要调用mmc_add_host向内核注册mmc host

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); //开启host,我们来看看这个函数的行为到底是什么
	if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
		register_pm_notifier(&host->pm_notify);

	return 0;
}
mmc_start_host(host)贴出代码如下:
void mmc_start_host(struct mmc_host *host)
{
	mmc_power_off(host);
【
void mmc_power_off(struct mmc_host *host)
{
	int err = 0;
	mmc_host_clk_hold(host);

	host->ios.clock = 0;//时钟频率设置为0
	host->ios.vdd = 0;//因为是刚注册host,因此host的电压先设置为0
.......
	/*
	 * Reset ocr mask to be the highest possible voltage supported for
	 * this mmc host. This value will be used at next power up.
	 */
	host->ocr = 1 << (fls(host->ocr_avail) - 1);

	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;//data 的bus宽度设置为1bit
	host->ios.timing = MMC_TIMING_LEGACY;
	mmc_set_ios(host);//调用mmc 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);
}
】
	mmc_detect_change(host, 0); 
【
	void mmc_detect_change(struct mmc_host *host, unsigned long delay)
{
#ifdef CONFIG_MMC_DEBUG
	unsigned long flags;
	spin_lock_irqsave(&host->lock, flags);
	WARN_ON(host->removed);
	spin_unlock_irqrestore(&host->lock, flags);
#endif
	host->detect_change = 1;

	wake_lock(&host->detect_wake_lock);
	mmc_schedule_delayed_work(&host->detect, delay); //提交调度delay work,延时为0妙,这样就意味着,会立刻调用mmc_scan函数,开始探测sd卡,或者mmc/sdio卡。对于一些sdio功能卡,非可插拔的话,这里就是探测sdio功能卡的启动点。
}
】
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值