MMC/SD子系统里驱动工程师负责的部分

本文探讨SD驱动子系统中Host主机控制层的角色。Host层主要任务包括:初始化控制器,注册中断和时钟,实现mmc_host_ops结构体以处理硬件操作。关键函数如s3cmci_request用于发送请求,s3cmci_irq处理中断,s3cmci_set_ios设置时钟和电源。通过对平台设备的probe,驱动能够识别并操作SD/MMC卡。
摘要由CSDN通过智能技术生成

对于SD驱动子系统里,只有一部分和硬件挂钩,就是Host主机控制层,对于block块设备层存软件的,就是实现一个块设备结构体,然后注册一个请求处理函数而已(这个函数会最终会调用到主机控制器层的请求函数),这个共性的不需要我们考虑。而对于Core核心层来说,和SD卡是紧密相关,但是这是协议层,仅仅实现协议,例如初始化卡的需要哪几部分,读取卡需要几步骤等,这里只是实现协议层,没有硬件操作。但是这协议层实现的函数会调用到Host核心层来实现发送命令数据等。

队以我们来说,如果想添加其他卡的操作,就修改core层,如果想添加MMC/SD控制器那就修改Host层,我们现在讨论主机控制层。主机控制层的任务:实现协议的底层实现。


看看Host层的架构:

首先Host层基于platform平台,通过probe获取主机控制器的寄存器地址和中断号:

static struct platform_driver s3cmci_driver = {

.probe = s3cmci_probe,

};

static int __init s3cmci_init(void)
{
return platform_driver_register(&s3cmci_driver);
}


static void __exit s3cmci_exit(void)
{
platform_driver_unregister(&s3cmci_driver);
}


static int __devinit s3cmci_probe(struct platform_device *pdev)

1、获取主机控制器的寄存器基地址和中断号,注册中断,使能时钟。如果有使用DMA还有申请DMA;

2、分配设置注册mmc_host结构体,这是主机控制器的操作结构体,主要就三个函数:

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

mmc->ops = &s3cmci_ops;

ret = mmc_add_host(mmc);


mmc_alloc_host函数在核心层实现的,最为核心的函数就是INIT_DELAYED_WORK(&host->detect, mmc_rescan)勘测函数绑定,mmc_add_host函数里最核心函数就是调用mmc_schedule_delayed_work(&host->detect, delay)函数,也就是调用mmc_rescan函数。如果当前没有卡那就在mmc_rescan里直接返回,如果有卡就会发送连锁反应。这个mmc_rescan函数还会在中断发生,素以如果插入卡也会调用。这个函数会枚举卡并通过mmc_attach_mmc函数初始化卡,最主要就是调用mmc_init_card和mmc_add_card函数进而触发块设备驱动block里的probe函数被调用而初始化好块设备,进而把块设备和主机控制器都运作起来。


对于Host层另一个重要任务就是实现mmc->ops = &s3cmci_ops操作函数了,里面包含协议用到的硬件处理层:

static struct mmc_host_ops s3cmci_ops = {
.request = s3cmci_request,   //发送请求数据硬件操作函数
.set_ios = s3cmci_set_ios,  //设置时钟电压等
.get_ro = s3cmci_get_ro,  //判断卡是否为只读
.get_cd = s3cmci_card_present, //判断卡是否在插槽
.enable_sdio_irq = s3cmci_enable_sdio_irq,  //使能中断
};


对于请求来说块设备的请求处理函数还调用核心层,核心层会调用mmc_host_ops 的请求:

static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)

{

//实现把请求(也就是命令)发送

//启动数据传输模式:FIFO/DMA,,要初始化好,然后使能中断

}


当命令发完之后有数据读写时候会产生中断(在probe注册了)

static irqreturn_t s3cmci_irq(int irq, void *dev_id)

{

//判断是不是发送接收数据中断,哈市完成中断,还是出错中断,然后进行处理

例如FIFO:

if (host->pio_active == XFER_WRITE)
do_pio_write(host);


if (host->pio_active == XFER_READ)
do_pio_read(host);

}



到这里请求就结束了。剩下的几个函数也是一样,都是硬件操作:


static int s3cmci_get_ro(struct mmc_host *mmc)
{

ret = gpio_get_value(pdata->gpio_wprotect) ? 1 : 0;  //读取引脚值就知道卡是否处于保护状态
............
}


static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{

//电源on/off设置,时钟频率从设置、SD卡总线宽度设置

}

static int s3cmci_card_present(struct mmc_host *mmc)
{

//判断一个引脚电平就可以知道卡是否在卡槽

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值