Linux Platform总线
来源:互联网 发布:mysql数据库主从复制 编辑:程序博客网 时间:2024/06/04 18:14
LINUX
为了完成LCD设备的注册,将其放进/arch/arm/mach-s3c2440/mach-smdk2440.c中定义的smdk2440_devices数组中:
在driver中用platform_get_resource()或platform_get_irq()等函数获取设备资源
获取到的内存或IO资源,需要ioremap后才能使用
获取到的IRQ资源,需要request_irq
platform_data可以自定义,比如DM9000驱动,用platform_data描述它的一些属性:
在设备驱动程序中经常会见到和platform相关的字段,分布在驱动程序的多个角落,这也是2.6内核中比较重要的一种机制,把它的原理弄懂了,对以后分析驱动程序很有帮助,下面简单介绍一下:
在linux2.6设备模型中,关心总线,设备,驱动这三个实体,总线将设备和驱动绑定,在系统每注册一个设备的时候,会寻找与之匹配的驱动。相反,在系统每注册一个驱动的时候,寻找与之匹配的设备,匹配是由总线来完成的。
一个现实的Linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI、USB、I2C、SPI 等的设备而言,这自然不是问题,但是在嵌入式系统里面,SoC 系统中集成的独立的外设控制器、挂接在SoC 内存空间的外设等确不依附于此类总线。基于这一背景,Linux 发明了一种虚拟的总线,称为platform 总线
SOC系统中集成的独立外设单元(I2C,LCD,SPI,RTC等)都被当作平台设备来处理,而它们本身是字符型设备。
从Linux2.6内核起,引入一套新的驱动管理和注册机制:platform_device 和 platform_driver 。Linux 中大部分的设备驱动,都可以使用这套机制,设备用 platform_device 表示;驱动用platform_driver 进行注册。
一个现实的Linux 设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCI、USB、I2C、SPI 等的设备而言,这自然不是问题,但是在嵌入式系统里面,SoC 系统中集成的独立的外设控制器、挂接在SoC 内存空间的外设等确不依附于此类总线。基于这一背景,Linux 发明了一种虚拟的总线,称为platform 总线
SOC系统中集成的独立外设单元(I2C,LCD,SPI,RTC等)都被当作平台设备来处理,而它们本身是字符型设备。
从Linux2.6内核起,引入一套新的驱动管理和注册机制:platform_device 和 platform_driver 。Linux 中大部分的设备驱动,都可以使用这套机制,设备用 platform_device 表示;驱动用platform_driver 进行注册。
platform_device 结构体 include/linux/platform_device.h
- struct platform_device
- {
- const char *name; //设备名
- u32 id;
- struct device dev;
- u32 num_resources; //设备所使用的各类资源数量
- struct resource *resource;//使用的资源
- }
platform_driver 结构体 include/linux/platform_device.h
- struct platform_driver
- {
- int (*probe)(struct platform_device*);
- int (*remove)(struct platform_device*);
- void (*shutdown)(struct platform_device*);
- int (*suspend)(struct platform_device*, pm_message_t state);
- int (*suspend_late)(struct platform_device*, pm_message_t state);
- int (*resume_early)(struct platform_device*);
- int (*resume)(struct platform_device*);
- struct pm_ext_ops *pm;
- struct device_driver driver;
- };
系统为platform总线定义一个bus_type的实例platform_bus_type,通过其成员函数match(),确定device和driver如何匹配。
匹配platform_device和platform_driver主要看二者的name字段是否相同。(name必须要相同才能匹配)
匹配platform_device和platform_driver主要看二者的name字段是否相同。(name必须要相同才能匹配)
用platform_device_register()函数注册单个的平台设备。
一般是在平台的BSP文件中定义platform_device,通过platform_add_devices()函数将平台设备注册到系统中
一般是在平台的BSP文件中定义platform_device,通过platform_add_devices()函数将平台设备注册到系统中
platform_driver 的注册与注销:
platform_driver_register()
platform_driver_unregister()
以s3c2440 LCD驱动为例:
在BSP文件中:
platform_driver_register()
platform_driver_unregister()
以s3c2440 LCD驱动为例:
在BSP文件中:
- struct platform_device s3c_device_lcd = {
- .name = "s3c2410-lcd",
- .id = -1,
- .num_resources = ARRAY_SIZE(s3c_lcd_resource),
- .resource = s3c_lcd_resource,
- .dev ={
- .dma_mask =&s3c_device_lcd_dmamask,
- .coherent_dma_mask = 0xffffffffUL
- }
- };
为了完成LCD设备的注册,将其放进/arch/arm/mach-s3c2440/mach-smdk2440.c中定义的smdk2440_devices数组中:
- static struct platform_device *smdk2440_devices[] __initdata= {
- ........
- ........
- &s3c_device_lcd,
- };
由platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));注册
在相应的driver文件中:(/drivers/video/s3c2410fb.c)
- static struct platform_driver s3c2410fb_driver = {
- .probe = s3c2410fb_probe,//驱动探测
- .remove = __devexit_p(s3c2410fb_remove),//驱动移除
- .suspend = s3c2410fb_suspend,
- .resume = s3c2410fb_resume,
- .driver ={
- .name ="s3c2410-lcd",//和platform_device中的name相同
- .owner = THIS_MODULE,
- },
- };
- static int __devinit s3c2410_fb_init(void)
- {
- return platform_driver_register(&s3c2410fb_driver);
- }
- static void __exit s3c2410fb_cleanup(void)
- {
- platform_driver_unregister(&s3c2410fb_driver);
- }
注册成功后会在下面两个目录下看到设备节点:
/sys/bus/platform/devices/
/sys/devices/platform/
/sys/bus/platform/devices/
/sys/devices/platform/
平台设备资源和数据:
resource结构体:
resource结构体:
- struct resource
- {
- resource_size_t start;
- resource_size_t end;
- const char *name;
- unsigned long flags;
- struct resource *parent,*sibling, *child;
- };
我们通常关心start、end 和flags 这3 个字段,分别标明资源的开始值、结束值和类型,flags
可以为IORESOURCE_IO、IORESOURCE_MEM、IORESOURCE_IRQ、IORESOURCE_DMA 等。
可以为IORESOURCE_IO、IORESOURCE_MEM、IORESOURCE_IRQ、IORESOURCE_DMA 等。
如LCD资源:
- static struct resource s3c_lcd_resource[]= {
- [0]= {
- .start = S3C24XX_PA_LCD, //LCD的IO资源起始地始(LCD控制器寄存器地址)
- .end= S3C24XX_PA_LCD + S3C24XX_SZ_LCD- 1, //结束地址
- .flags = IORESOURCE_MEM,
- },
- [1]= {
- .start = IRQ_LCD, //LCD中断号
- .end= IRQ_LCD,
- .flags = IORESOURCE_IRQ,
- }
- };
在driver中用platform_get_resource()或platform_get_irq()等函数获取设备资源
- struct resource *platform_get_resource(struct platform_device*, unsignedint, unsigned
- int);
- int platform_get_irq(struct platform_device*dev, unsignedint num);
获取到的内存或IO资源,需要ioremap后才能使用
获取到的IRQ资源,需要request_irq
设备除了可以在BSP 中定义资源以外,还可以附加一些数据信息,因为对设备的硬件描述除了中断、内存、DMA 通道以外,可能还会有一些配置信息,而这些配置信息也依赖于板,不适宜直接放置在设备驱动本身,因此,platform 也提供了platform_data 的支持。
platform_data可以自定义,比如DM9000驱动,用platform_data描述它的一些属性:
- static struct dm9000_plat_data s3c_dm9000_platdata= {
- .flags = DM9000_PLATF_16BITONLY,
- };
- static struct platform_device s3c_device_dm9000 ={
- .name ="dm9000",
- .id = 0,
- .num_resources = ARRAY_SIZE(s3c_dm9000_resource),
- .resource = s3c_dm9000_resource,
- .dev ={
- .platform_data = &s3c_dm9000_platdata,
- }
- };
在相应的驱动中使用:
struct dm9000_plat_data *pdata = pdev->dev.platform_data;
可获取platform_data
struct dm9000_plat_data *pdata = pdev->dev.platform_data;
可获取platform_data
找一个和平台相关的驱动程序,从BSP文件开始分析它的结构,一直分析到它的最底层的硬件操作,这样很快就能熟悉platform的工作原理
0 0
- linux platform 虚拟总线
- Linux Platform总线
- Linux Platform总线+SPI总线分析
- Linux Platform总线+SPI总线分析
- linux驱动之platform总线
- Linux驱动---------platform总线设备
- Linux驱动Platform总线模型
- [Linux驱动入门]Platform总线
- linux下platform总线驱动
- linux中platform总线解析(一)(platform总线初始化)
- Linux设备模型之platform总线
- Linux设备驱动模型之platform总线
- Linux设备模型之platform总线
- LINUX设备驱动之platform总线
- Linux设备驱动模型之platform总线
- Linux设备模型之platform总线
- Linux虚拟总线platform设备和驱动
- Linux设备模型之platform总线
- 路由器的ARP绑定
- 最新Android ADT报parseSdkContent failed java.lang.ExceptionInInitializerError异常的处理办法
- 返回Android游戏黑屏解决办法
- OC5_容器类型的快速枚举_数组排序
- UVA - 108 Maximum Sum 求子矩阵的最大和
- Linux Platform总线
- JAVA开源电商软件研究心得第四篇-OFBiz的安装和配置
- Anroid 异常:is not valid; is your activity running?
- 文件 是.exe结尾,怎么恢复
- HDU1071
- gravity 和layout_gravity 的使用
- Underlying DBMS error[ORA-12154: TNS: 无法解析指定的连接标识符
- 无线网络的各种安全性类型
- 【重头学习Android】关于UI切图和屏幕适配问题