Davinci MMC SD Driver详解
1、首先我们来看看Makefile
1 #
2 # Makefile for the kernel mmc device drivers.
3 #
4
5 #
6 # Core
7 #
8 obj-$(CONFIG_MMC) += mmc_core.o
9
10 #
11 # Media drivers
12 #
13 obj-$(CONFIG_MMC_BLOCK) += mmc_block.o
14
15 #
16 # Host drivers
17 #
18 obj-$(CONFIG_MMC_ARMMMCI) += mmci.o
19 obj-$(CONFIG_MMC_PXA) += pxamci.o
20 obj-$(CONFIG_MMC_IMX) += imxmmc.o
21 obj-$(CONFIG_MMC_SDHCI) += sdhci.o
22 obj-$(CONFIG_MMC_WBSD) += wbsd.o
23 obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
24 obj-$(CONFIG_MMC_OMAP) += omap.o
25 obj-$(CONFIG_MMC_AT91RM9200) += at91_mci.o
26 obj-$(CONFIG_MMC_DAVINCI) += davinci-mmc.o
27
28 mmc_core-y := mmc.o mmc_queue.o mmc_sysfs.o
29
30 ifeq ($(CONFIG_MMC_DEBUG),y)
31 EXTRA_CFLAGS += -DDEBUG
32 endif
从Makefile我们会知道davinci sd卡驱动需要davinci-mmc.c mmc.c mmc_queue.c mmc_sysfs.c mmc_block.c
其中davinci-mmc.c是我们需要移植或者编写的sd卡驱动程序,其他基本不需要更改;
以模块方式编得sd卡驱动:davinci-mmc.ko mmc_block.ko mmc_core.ko
2、下面我们先来看看mmc_core.ko,该模块如其名就是sd卡的核心,我们先找个该模块的入口,在mmc_sysfs.c中:mmc_init函数
347 static int __init mmc_init(void)
348 {
349 int ret;
350 workqueue = create_singlethread_workqueue("kmmcd");
351 if(!workqueue)
352 return -ENOMEM;
353 ret = bus_register(&mmc_bus_type);
354 if (ret == 0) {
355 ret = class_register(&mmc_host_class);
356 if (ret)
357 bus_unregister(&mmc_bus_type);
358 }
359 return ret;
360 }
361
362 static void __exit mmc_exit(void)
363 {
364 class_unregister(&mmc_host_class);
365 bus_unregister(&mmc_bus_type);
366 destroy_workqueue(workqueue);
367 }
368
369 module_init(mmc_init);
370 module_exit(mmc_exit);
首先看mmc_init(),这是系统启动后将要调用的;
在mmc_init函数中,主要完成3项工作 :
a:workqueue = create_singlethread_workqueue("kmmcd");//创见一个单线程的工作队列
b:bus_register(&mmc_bus_type);//注册总线
c:class_register(&mmc_host_class);//注册mmc_host_class类
首先是创建工作队列,名为kmmcd:如下:
857 tts/1 Ss 0:00 -sh
858 ? S 0:00 ./wis-streamer -s
859 ? S 0:00 ./wis-streamer -s
860 ? S 0:00 ./wis-streamer -s
861 ? S 0:00 ./wis-streamer -s
876 ? S< 0:00 [kmmcd]
877 tts/1 R+ 0:00 ps x
第二步是注册总线,我们来看下/SYS/BUS/MMC
#
# ls /sys/bus/mmc/
devices drivers
#
目录下面有devices和drivers两个目录,其实对应的是bus_type中的两条链表
Bus_type结构如下:
struct bus_type {
const char * name;
struct subsystem subsys;
struct kset drivers;
struct kset devices;
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs;
struct driver_attribute * drv_attrs;
int (*match)(struct device * dev, struct device_driver * drv);
int (*uevent)(struct device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
int (*probe)(struct device * dev);
int (*remove)(struct device * dev);
void (*shutdown)(struct device * dev);
int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
其中name字段为“MMC”,就对应于bus目录下的mmc目录;直插入core,drivers和devices目录下面是什么也没有的,然后是注册mmc_host_class类,在/SYS/CLASS/下面会生产host_mmc目录:如下
# ls /sys/class/
/sys/class/cmem/ /sys/class/net/
/sys/class/davinci_display/ /sys/class/ppp/
/sys/class/davinci_system/ /sys/class/rtc-dev/
/sys/class/dm365mmap/ /sys/class/rtc/
/sys/class/edma/ /sys/class/scsi_device/
/sys/class/i 2c -adapter/ /sys/class/scsi_disk/
/sys/class/i 2c -dev/ /sys/class/scsi_generic/
/sys/class/input/ /sys/class/scsi_host/
/sys/class/irqk/ /sys/class/sound/
/sys/class/iscsi_connection/ /sys/class/spi_master/
/sys/class/iscsi_host/ /sys/class/spidev/
/sys/class/iscsi_session/ /sys/class/tty/
/sys/class/iscsi_transport/ /sys/class/usb_device/
/sys/class/mem/ /sys/class/usb_host/
/sys/class/misc/ /sys/class/vc/
/sys/class/mmc_host/ /sys/class/video4linux/
/sys/class/mtd/ /sys/class/vtconsole/
# ls /sys/class/mmc_host/
#
接下来我们看下mmc_bus_type的定义,我们sd卡总线就是这条总线了:
static struct bus_type mmc_bus_type = {
.name = "mmc",
.dev_attrs = mmc_dev_attrs,
.match = mmc_bus_match,
.uevent = mmc_bus_uevent,
.probe = mmc_bus_probe,
.remove = mmc_bus_remove,
.suspend = mmc_bus_suspend,
.resume = mmc_bus_resume,
};
我们主要关注mmc_bus_match与mmc_bus_probe,此两函数将要在device_register和driver_register向总线注册设备的时候被调用。
下面解释关键的函数:
/*
* This currently matches any MMC driver to any MMC card - drivers
* themselves make the decision whether to drive this card in their
* probe method. However, we force "bad" cards to fail.
*/
static int mmc_bus_match(struct device *dev, struct device_driver *drv)
{
struct mmc_card *card = dev_to_mmc_card(dev);
return !mmc_card_bad(card);
}
#define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD)
这个函数主要是判断卡的状态;如果卡位bad,则返回真;
static int mmc_bus_probe(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = dev_to_mmc_card(dev);
return drv->probe(card);//调用mmc_block里面的probe函数;
}
static struct class mmc_host_class = {
.name = "mmc_host",//正如我们所看到的那样
.release = mmc_host_classdev_release,
};