前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设备驱动外传 – 虚拟总线和platform device「建议收藏」

设备驱动外传 – 虚拟总线和platform device「建议收藏」

作者头像
全栈程序员站长
发布2022-09-15 11:35:55
4940
发布2022-09-15 11:35:55
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

1. 总论

2. 系统初始化 platform device

3. 驱动程序使用 platform device

1. 总论

Linux-2.6.11引入了设备模型的概念,将大部分设备驱动挂载到虚拟总线上。

其目的在于:

1) 提供友好的用户接口,用户可以在sys/bus/platform/下找到相应的驱动和设备。

2) 更有利于电源管理。

2. 系统初始化 platform device

在驱动程序的初始化函数 xxx_probe(struct platform_device *pdev)中,其结构体参数platform_device,是在系统初始化过程中发现了该设备存在的前提条件下,通过platform_device_register(dev) 完成注册的,并且struct platform_device的结构变量被赋值。

以Xscal初始化sd卡控制器为例,

/* linux/arch/arm/mach-pxa/starwood_p1.c */

MACHINE_START(SAAR, “PXA935 handheld Platform (Starwood P1)”) … … .init_machine = saar_init, MACHINE_END

static void __init saar_init(void) { … …

saar_init_mmc();

… … }

static void __init saar_init_mmc(void) { … … pxa_set_mci_info(&saar_mci_platform_data); //saar_mci_platform_data完成该设备特有数据的赋值 … … }

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, //回调函数,设置sd卡控制器的探测中断pin脚 gpio_cd .exit = saar_mci_exit, };

void __init pxa_set_mci_info(struct pxamci_platform_data *info) { pxa_register_device(&pxa_device_mci, info); }

struct platform_device pxa_device_mci = { //完成结构体platform_device的赋值 .name = “pxa2xx-mci”, //芯片的设备名称,驱动通过匹配该名字找到设备 .id = 0, .dev = { .dma_mask = &pxamci_dmamask, .coherent_dma_mask = 0xffffffff, }, .num_resources = ARRAY_SIZE(pxamci_resources), .resource = pxamci_resources, //设置芯片的物理地址 };

void __init pxa_register_device(struct platform_device *dev, void *data) { … …

dev->dev.platform_data = data; //将该设备特有的数据挂到 dev->dev.platform_data下

platform_device_register(dev);

… … }

3. 驱动程序使用 platform device

驱动程序通过platform_driver_register()找到与该驱动对应的设备,完成驱动和设备的绑定,并且挂载到虚拟总线上。

具体过程如下,

platform_driver_register(struct platform_driver *drv);

|

driver_register(&drv->driver);

|

bus_add_driver(drv);

|

driver_attach(drv);

int driver_attach(struct device_driver *drv) { return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); //__driver_attach最后调用driver_bound(dev); }

int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *, void *)) { … … while ((dev = next_device(&i)) && !error) fn(dev, data); //fn即__driver_attach,完成设备与驱动的绑定

… … }

static void driver_bound(struct device *dev) { … …

klist_add_tail(&dev->knode_driver, &dev->driver->p->klist_devices); }

驱动程序找到了自己所对应的设备之后,就可以对该设备初始化了,即probe()操作,在probe()中,便可以使用platform_device结构体里的数据了。

仍然以sd卡控制器为例,

/* linux/drivers/mmc/host/pxamci.c */

static int __init pxamci_init(void) { … … return platform_driver_register(&pxamci_driver); }

static struct platform_driver pxamci_driver = { .probe = pxamci_probe, … … };

static int pxamci_probe(struct platform_device *pdev) {

struct resource *r;

/*

* 得到sd卡控制器芯片的物理地址

*/

r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);

host->res = r;

/*

* 得到sd卡控制器芯片的内部中断源并申请中断

*/

irq = platform_get_irq(pdev, 0);

host->irq = irq; request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);

… … }

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/163805.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档