Linux设备驱动子系统第二弹- SD卡 - 图文(3)

2019-08-31 13:59

其中,remove为probe的反操作,suspend和resume涉及电源管理的内容,本文重点讨论probe。

SD主控制器驱动程序的初始化函数probe(struct platform_device *pdev),概括地讲,主要完成五大任务,

? ? ? ? ?

初始化设备的数据结构,并将数据挂载到pdev->dev.driver_data下 实现设备驱动的功能函数,如mmc->ops = &pxamci_ops; 申请中断函数request_irq()

注册设备,即注册kobject,建立sys文件,发送uevent等 其他需求,如在/proc/driver下建立用户交互文件等

2.2.1 注册设备

对于设备的注册,所有设备驱动的相关代码都类似。 static int pxamci_probe(struct platform_device *pdev) {

mmc = mmc_alloc_host(sizeof(struct pxamci_host), &pdev->dev); mmc_add_host(mmc); ... ... }

这两个函数都由/drivers/mmc/core核心层下的host.c负责具体实现, 1) mmc_alloc_host

为主设备控制器建立数据结构,建立kobject,并初始化等待队列,工作队列,以及一些控制器的配置。其中,INIT_DELAYED_WORK(&host->detect, mmc_rescan);将探测SD卡的函数mmc_rescan与工作队列host->detect关联,mmc_rescan是整个SD子系统的核心函数,本文第三部分协议层将对它作重点讨论。

struct mmc_host *mmc_alloc_host(int extra, struct device *dev) {

/* 建立数据结构 */ struct mmc_host *host;

host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); /* 建立kobject */ host->parent = dev;

host->class_dev.parent = dev;

host->class_dev.class = &mmc_host_class; device_initialize(&host->class_dev); /* 初始化等待队列,工作队列 */ init_waitqueue_head(&host->wq);

INIT_DELAYED_WORK(&host->detect, mmc_rescan);

/* 配置控制器 */

host->max_hw_segs = 1; host->max_phys_segs = 1; ... ... return host; }

2) mmc_add_host

完成kobject的注册,并调用mmc_rescan,目的在于在系统初始化的时候就扫描SD总线查看是否存在SD卡。注意到这里的工作队列的延时时间delay为0,因为系统启动的时候不考虑插拔SD卡,关于这个delay将在下文讨论。 int mmc_add_host(struct mmc_host *host) {

device_add(&host->class_dev); mmc_start_host(host);

... ... }

void mmc_start_host(struct mmc_host *host) {

mmc_power_off(host); mmc_detect_change(host, 0); }

void mmc_detect_change(struct mmc_host *host, unsigned long delay) {

mmc_schedule_delayed_work(&host->detect, delay); }

static int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay) {

wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ * 2); return queue_delayed_work(workqueue, work, delay); }

2.2.2 为设备赋初值

其实,整个设备驱动的probe()函数,其本质就是是为设备建立起数据结构并对其赋初值。pxamci_probe(struct platform_device *pdev)主要为SD主控制器完成时钟、存储等方面的初始化配置,

static int pxamci_probe(struct platform_device *pdev) {

struct mmc_host *mmc;

struct pxamci_host *host = NULL;

mmc->ops = &pxamci_ops; mmc->max_phys_segs = NR_SG; mmc->max_hw_segs = NR_SG; mmc->max_seg_size = PAGE_SIZE; host = mmc_priv(mmc); host->mmc = mmc; host->dma = -1;

host->pdata = pdev->dev.platform_data; host->clkrt = CLKRT_OFF;

host->clk = clk_get(&pdev->dev, \ host->clkrate = clk_get_rate(host->clk);

mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL);

host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW, pxamci_dma_irq, host); ... ... }

完成所有赋值后,通过platform_set_drvdata(pdev, mmc);将数据挂载到pdev->dev.driver_data。

所有赋值中,我们重点关注从platform_device *pdev里得到的数据。platform_device *pdev是在系统初始化的时候扫描platform总线发现SD主控制器后所得到的数据。 1) 得到platform_data数据 先看看platform_device的结构, struct platform_device { const char * name; int id;

struct device dev; u32 num_resources; struct resource * resource; };

系统初始化的时候,已经为该SD主控制器的name, resources等赋上了初值,具体内容如下,

struct platform_device pxa_device_mci = { .name = \pxa2xx-mci\ .id = 0, .dev = {

.dma_mask = &pxamci_dmamask, .coherent_dma_mask = 0xffffffff, },

.num_resources = ARRAY_SIZE(pxamci_resources),

.resource = pxamci_resources, };

static struct resource pxamci_resources[] = { [0] = {

.start = 0x41100000, .end = 0x41100fff,

.flags = IORESOURCE_MEM, // SD主控制器芯片的起始地址 }, [1] = {

.start = IRQ_MMC, /* #define IRQ_MMC 23 */ .end = IRQ_MMC,

.flags = IORESOURCE_IRQ, // 申请的中断号 }, ... ... };

需要注意的是,platform_device数据结构里的name, id, resource等是所有设备都用的到的数据类型,那么设备自身独有的特性如何表现出来呢?事实上,结构体device专门准备了一个成员platform_data,就是为了挂载设备的一些特有的数据。(注意与driver_data相区别) struct device {

void *platform_data; /* Platform specific data, device core doesn't touch it */ void *driver_data; /* data private to the driver */ ... ... }

看看SD主控制器为什么会有这些特有数据,

static struct pxamci_platform_data saar_mci_platform_data = { .detect_delay = 50,

.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .init = saar_mci_init, .exit = saar_mci_exit, };

-> detect_delay

就是刚才提到的工作队列的延时时间,设置为50ms,由于各种SD主控制器芯片的性能不同,这个值可能会变化。那么为什么要为工作队列加一个延迟呢?首先,当插入SD卡之后,SD主控制器上的探测引脚会产生一个中断,之后调用中断函数里的工作队列,然后执


Linux设备驱动子系统第二弹- SD卡 - 图文(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:太阳能热水器控制仪使用说明书资料

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: