linux-mmc

MMC/SD设备驱动分为三个文件夹:host、card、core,这三个文件夹联系的非常紧密,初始化也好、扫描也好、读写也好,总是跳来跳去。

一 host的分配和添加

先看看初始化吧,host分配的代码位于driver/mmc/host/s3cmci.c。

s3cmci_probe()中的重要函数

mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);

1 host->rescan_disable = 1;失能card检测。
2 给host分配index,类似ID;
(1) 分配idr的后备资源,预备役。idr_pre_get(&mmc_host_idr, GFP_KERNEL);
(2) get一个与host相关联的id到&host->index。err = idr_get_new(&mmc_host_idr, host, &host->index);
3 初始化等待队列头。init_waitqueue_head(&host->wq);
4 初始化延时工作队列工作。INIT_DELAYED_WORK(&host->detect, mmc_rescan);
(1) (_work)->func = (_func);
(2) 初始化&(_work)->timer定时器,到期的回调函数为delayed_work_timer_fn。

void delayed_work_timer_fn(unsigned long __data)
{
	struct delayed_work *dwork = (struct delayed_work *)__data;
	struct cpu_workqueue_struct *cwq = get_work_cwq(&dwork->work);

	/* should have been called from irqsafe timer with irq already off */
	__queue_work(dwork->cpu, cwq->wq, &dwork->work);
} 

ret = mmc_add_host(mmc);
ret = mmc_add_host(mmc);
  mmc_start_host(host);
  mmc_detect_change(host, 0);
    mmc_schedule_delayed_work(&host->detect, delay);
static struct workqueue_struct *workqueue;
static int mmc_schedule_delayed_work(struct delayed_work *work,
				     unsigned long delay)
{
	return queue_delayed_work(workqueue, work, delay);
} 

调度一个延时工作项,就是加入到workqueue,最后会insert到线程池worker_pool的worklist上;delay == 0马上加入,否则,add timer,等到定时到期的回调函数中会执行相同的功能。
mmc_power_off(host);名为断电;包括一些io设置等。
这些工作做完,mmc_rescan()就开始运行了,它是用来扫描card的。

二 card的分配和添加

这里就进入core的mmc_rescan()了。
void mmc_rescan(struct work_struct *work)

1 if (host->rescan_disable)就直接return了,所以一定要使能card检测。
2 host->bus_ops是个什么东西?第一次rescan时,它是NULL的。
3 请求一个host控制器。
mmc_claim_host(host);
  __mmc_claim_host(host, NULL);
(1) 初始化话了一个等待队列wait_queue_t,添加到host->wq的等待队列头上。
(2) 设置当前进程是不可中断的。
(3) 查看是否满足终止、host可用、拥有host的是当前线程,满足则break;否则,没有获得host控制器的使用权,就schedule()调度出去。
(4) 设置当前进程为运行状态。
(5) 请求到控制器后,如果只有一张卡,stop会一直为0,没有冲突;那么设置一些请求标记;否则,stop为1,就wake up hots->wq上的等待队列;马上把这个等待队列wait从wq中remove。看来是要wake up其他的wait;为什么不先remove本wait,再wake up其他的?
(6) 如果没有停止,enble host。
(7) stop代表终止host的等待队列并唤醒。
4 mmc_rescan_try_freq(host, max(freqs[i], host->f_min)。
(1) power up
(2) 硬件reset,一是host->ops->hw_reset(host);2是发送CMD52 reset sdio,sd/mmc忽略此命令。
(3) CMD0,设置卡为idle state,注意,如果DAT3/nCS是低电平,就进入SPI模式了。
(4) CMD8,ACM41之前一定会发送这个cmd,SD2.0会响应;SD1.0会fail,区分出来后为什么没有保存?


CMD8的参数:cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;spec2.0:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值