一、注册一个平台设备
方法1:platform_device_register
核心数据结构:
1 struct platform_device { 2 const char *name; 3 int id; 4 bool id_auto; 5 struct device dev; 6 u32 num_resources; 7 struct resource *resource; 8 9 const struct platform_device_id *id_entry; 10 char *driver_override; /* Driver name to force a match */ 11 12 /* MFD cell pointer */ 13 struct mfd_cell *mfd_cell; 14 15 /* arch specific additions */ 16 struct pdev_archdata archdata; 17 };
核心接口
1 extern int platform_device_register(struct platform_device *);
代码示例
static struct resource my_resoure1[]={ { .start = 0x00, .end = 0x10, .name = "resource1 MEM", .flags = IORESOURCE_MEM, }, { .start = 0x11, .end = 0x20, .name = "resource2 MEM", .flags = IORESOURCE_MEM, }, { .start = 5, .end = 9, .name = "resource3 IRQ", .flags = IORESOURCE_IRQ, }, { .start = 10, .end = 15, .name = "resource4 IRQ", .flags = IORESOURCE_IRQ, }, }; static struct platform_device my_device1 = { .name = "xym-test-platform-device-1", .id = -1, .num_resources = ARRAY_SIZE(my_resoure1), .resource = my_resoure1, .dev = { .release = my_platform_device_release, //不注册此接口,卸载驱动时会报警告 .platform_data = &platform_data_1, }, }; struct platform_device * p_device_1 = &my_device1; //device 1 ret = platform_device_register(&my_device1); if (ret) { printk(KERN_INFO"Unable to device 1 register(%d)\n", ret); return ret; }
方法2:platform_device_register_full
核心数据结构
1 struct platform_device_info { 2 struct device *parent; 3 struct fwnode_handle *fwnode; 4 5 const char *name; 6 int id; 7 8 const struct resource *res; 9 unsigned int num_res; 10 11 const void *data; 12 size_t size_data; 13 u64 dma_mask; 14 };
核心接口
1 extern struct platform_device *platform_device_register_full(const struct platform_device_info *pdevinfo); 2 3 static inline struct platform_device *platform_device_register_simple( 4 const char *name, int id, 5 const struct resource *res, unsigned int num) 6 7 static inline struct platform_device *platform_device_register_resndata( 8 struct device *parent, const char *name, int id, 9 const struct resource *res, unsigned int num, 10 const void *data, size_t size)
代码示例
static struct resource my_resoure2[]={ { .start = 0x21, .end = 0x30, .name = "resource1 MEM", .flags = IORESOURCE_MEM, }, { .start = 0x31, .end = 0x40, .name = "resource2 MEM", .flags = IORESOURCE_MEM, }, { .start = 20, .end = 30, .name = "resource3 IRQ", .flags = IORESOURCE_IRQ, }, { .start = 40, .end = 50, .name = "resource4 IRQ", .flags = IORESOURCE_IRQ, }, }; static struct platform_device_info my_device_2 = { .name = "xym-test-platform-device-2", .id = -1, .num_res = ARRAY_SIZE(my_resoure2), .res = my_resoure2, .data = &platform_data_2, .size_data = sizeof(platform_data_2), }; struct platform_device * p_device_2; //device 2 p_device_2 = platform_device_register_full(&my_device_2); if (!p_device_2) { printk(KERN_INFO"Unable to device 2 register\n"); return ret; }
static struct resource my_resoure3[]={ { .start = 0x41, .end = 0x50, .name = "resource1 MEM", .flags = IORESOURCE_MEM, }, { .start = 0x51, .end = 0x60, .name = "resource2 MEM", .flags = IORESOURCE_MEM, }, { .start = 60, .end = 70, .name = "resource3 IRQ", .flags = IORESOURCE_IRQ, }, { .start = 80, .end = 90, .name = "resource4 IRQ", .flags = IORESOURCE_IRQ, }, }; struct platform_device * p_device_3; p_device_3 = platform_device_register_resndata(NULL, "xym-test-platform-device-3",-1,my_resoure3,ARRAY_SIZE(my_resoure3),&platform_data_3,sizeof(platform_data_3)); if (!p_device_3) { printk(KERN_INFO"Unable to device 3 register\n"); return ret; }
static struct resource my_resoure4[]={ { .start = 0x61, .end = 0x70, .name = "resource1 MEM", .flags = IORESOURCE_MEM, }, { .start = 0x71, .end = 0x80, .name = "resource2 MEM", .flags = IORESOURCE_MEM, }, { .start = 100, .end = 110, .name = "resource3 IRQ", .flags = IORESOURCE_IRQ, }, { .start = 120, .end = 130, .name = "resource4 IRQ", .flags = IORESOURCE_IRQ, }, }; struct platform_device * p_device_4; //device 4 p_device_4 = platform_device_register_simple("xym-test-platform-device-4",-1,my_resoure4,ARRAY_SIZE(my_resoure4)); if (!p_device_4) { printk(KERN_INFO"Unable to device 4 register\n"); return ret; }
方法3、DTS注册
/ { platform_device_test,test{ compatible = "dts_test"; #address-cells = <1>; #size-cells = <1>; reg = <0x500 0x32>,<0x200 0x32>; reg-names = "test mem1","resource2 MEM"; interrupt-parent = <&vic0>; interrupts = <IRQ_TIMER0>,<IRQ_TIMER1>; interrupt-names = "test irq1","resource4 IRQ"; }; };
二、获取平台设备资源
核心接口
1 extern struct resource *platform_get_resource(struct platform_device *unsigned int, unsigned int); 2 extern int platform_get_irq(struct platform_device *, unsigned int); 3 extern struct resource *platform_get_resource_byname(struct platform_device *,unsigned int,const char *); 4 extern int platform_get_irq_byname(struct platform_device *, const char *);
代码示例
struct resource *presource; int irq = 0; printk(KERN_INFO"---------------------------\n"); printk(KERN_INFO"%s\n",__func__); printk(KERN_INFO"%s\n",pdev->name); if(pdev->dev.platform_data) { printk(KERN_INFO"platform_data is %d\n",*((int*)pdev->dev.platform_data)); } presource = platform_get_resource(pdev,IORESOURCE_MEM,0); if(!presource) { printk(KERN_INFO"get mem1 resource failed\n"); return -1; } printk(KERN_INFO"resoure1 name %s\n",presource->name); printk(KERN_INFO"resoure1 start 0x%08X\n",presource->start); printk(KERN_INFO"resoure1 end 0x%08X\n",presource->end); presource = NULL; presource = platform_get_resource_byname(pdev,IORESOURCE_MEM,"resource2 MEM"); if(!presource) { printk(KERN_INFO"get mem2 resource failed\n"); return -1; } printk(KERN_INFO"resoure1 name %s\n",presource->name); printk(KERN_INFO"resoure1 start 0x%08X\n",presource->start); printk(KERN_INFO"resoure1 end 0x%08X\n",presource->end); irq = platform_get_irq(pdev,0); if(irq < 0) { printk(KERN_INFO"get irq1 resource failed\n"); return -1; } printk(KERN_INFO"irq1 value is %d\n",irq); irq = 0; irq = platform_get_irq_byname(pdev,"resource4 IRQ"); if(irq < 0) { printk(KERN_INFO"get irq2 resource failed\n"); return -1; } printk(KERN_INFO"irq2 value is %d\n",irq); printk(KERN_INFO"---------------------------\n\n\n");
三、销毁设备
1 platform_device_unregister(&my_device); 2 platform_device_unregister(p_device_2);
四、注册平台设备驱动
核心数据结构
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 (*resume)(struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; bool prevent_deferred_probe; };
核心接口
platform_driver_register
代码示例
static struct platform_driver my_driver1 = { .driver = { .name = "xym-test-platform-device-1", }, .probe = my_platform_probe, .remove = my_platform_remove, .shutdown = my_platform_shutdown, .suspend = my_platform_suspend, .resume = my_platform_resume, }; ret = platform_driver_register(&my_driver1); if (ret) { printk(KERN_INFO"Unable to driver 1 register(%d)\n", ret); return ret; }
其中,driver中的 ”.name“ 字段和device中的 ”.name“ 相同,即可完成驱动和设备的匹配,即进入probe阶段。
结果输出
完整代码如下:
#include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/ioport.h> static struct resource my_resoure1[]={ { .start = 0x00, .end = 0x10, .name = "resource1 MEM", .flags = IORESOURCE_MEM, }, { .start = 0x11, .end = 0x20, .name = "resource2 MEM", .flags = IORESOURCE_MEM, }, { .start = 5, .end = 9, .name = "resource3 IRQ", .flags = IORESOURCE_IRQ, }, { .start = 10, .end = 15, .name = "resource4 IRQ", .flags = IORESOURCE_IRQ, }, }; static struct resource my_resoure2[]={ { .start = 0x21, .end = 0x30, .name = "resource1 MEM", .flags = IORESOURCE_MEM, }, { .start = 0x31, .end = 0x40, .name = "resource2 MEM", .flags = IORESOURCE_MEM, }, { .start = 20, .end = 30, .name = "resource3 IRQ", .flags = IORESOURCE_IRQ, }, { .start = 40, .end = 50, .name = "resource4 IRQ", .flags = IORESOURCE_IRQ, }, }; static struct resource my_resoure3[]={ { .start = 0x41, .end = 0x50, .name = "resource1 MEM", .flags = IORESOURCE_MEM, }, { .start = 0x51, .end = 0x60, .name = "resource2 MEM", .flags = IORESOURCE_MEM, }, { .start = 60, .end = 70, .name = "resource3 IRQ", .flags = IORESOURCE_IRQ, }, { .start = 80, .end = 90, .name = "resource4 IRQ", .flags = IORESOURCE_IRQ, }, }; static struct resource my_resoure4[]={ { .start = 0x61, .end = 0x70, .name = "resource1 MEM", .flags = IORESOURCE_MEM, }, { .start = 0x71, .end = 0x80, .name = "resource2 MEM", .flags = IORESOURCE_MEM, }, { .start = 100, .end = 110, .name = "resource3 IRQ", .flags = IORESOURCE_IRQ, }, { .start = 120, .end = 130, .name = "resource4 IRQ", .flags = IORESOURCE_IRQ, }, }; static int platform_data_1 = 1; static int platform_data_2 = 2; static int platform_data_3 = 3; static int platform_data_4 = 4; static int my_platform_probe(struct platform_device * pdev) { struct resource *presource; int irq = 0; printk(KERN_INFO"---------------------------\n"); printk(KERN_INFO"%s\n",__func__); printk(KERN_INFO"%s\n",pdev->name); if(pdev->dev.platform_data) { printk(KERN_INFO"platform_data is %d\n",*((int*)pdev->dev.platform_data)); } presource = platform_get_resource(pdev,IORESOURCE_MEM,0); if(!presource) { printk(KERN_INFO"get mem1 resource failed\n"); return -1; } printk(KERN_INFO"resoure1 name %s\n",presource->name); printk(KERN_INFO"resoure1 start 0x%08X\n",presource->start); printk(KERN_INFO"resoure1 end 0x%08X\n",presource->end); presource = NULL; presource = platform_get_resource_byname(pdev,IORESOURCE_MEM,"resource2 MEM"); if(!presource) { printk(KERN_INFO"get mem2 resource failed\n"); return -1; } printk(KERN_INFO"resoure1 name %s\n",presource->name); printk(KERN_INFO"resoure1 start 0x%08X\n",presource->start); printk(KERN_INFO"resoure1 end 0x%08X\n",presource->end); irq = platform_get_irq(pdev,0); if(irq < 0) { printk(KERN_INFO"get irq1 resource failed\n"); return -1; } printk(KERN_INFO"irq1 value is %d\n",irq); irq = 0; irq = platform_get_irq_byname(pdev,"resource4 IRQ"); if(irq < 0) { printk(KERN_INFO"get irq2 resource failed\n"); return -1; } printk(KERN_INFO"irq2 value is %d\n",irq); printk(KERN_INFO"---------------------------\n\n\n"); return 0; } static int my_platform_remove(struct platform_device * pdev) { printk(KERN_INFO"%s\n",__func__); return 0; } static void my_platform_shutdown(struct platform_device *pdev) { printk(KERN_INFO"%s\n",__func__); } static int my_platform_suspend(struct platform_device * pdev, pm_message_t state) { printk(KERN_INFO"%s\n",__func__); return 0; } static int my_platform_resume(struct platform_device * pdev) { printk(KERN_INFO"%s\n",__func__); return 0; } static void my_platform_device_release(struct device *dev) { printk(KERN_INFO"%s\n",__func__); } static struct platform_device my_device1 = { .name = "xym-test-platform-device-1", .id = -1, .num_resources = ARRAY_SIZE(my_resoure1), .resource = my_resoure1, .dev = { .release = my_platform_device_release, //不注册此接口,卸载驱动时会报警告 .platform_data = &platform_data_1, }, }; struct platform_device * p_device_1 = &my_device1; static struct platform_driver my_driver1 = { .driver = { .name = "xym-test-platform-device-1", }, .probe = my_platform_probe, .remove = my_platform_remove, .shutdown = my_platform_shutdown, .suspend = my_platform_suspend, .resume = my_platform_resume, }; static struct platform_device_info my_device_2 = { .name = "xym-test-platform-device-2", .id = -1, .num_res = ARRAY_SIZE(my_resoure2), .res = my_resoure2, .data = &platform_data_2, .size_data = sizeof(platform_data_2), }; struct platform_device * p_device_2; static struct platform_driver my_driver2 = { .driver = { .name = "xym-test-platform-device-2", }, .probe = my_platform_probe, .remove = my_platform_remove, .shutdown = my_platform_shutdown, .suspend = my_platform_suspend, .resume = my_platform_resume, }; struct platform_device * p_device_3; static struct platform_driver my_driver3 = { .driver = { .name = "xym-test-platform-device-3", }, .probe = my_platform_probe, .remove = my_platform_remove, .shutdown = my_platform_shutdown, .suspend = my_platform_suspend, .resume = my_platform_resume, }; struct platform_device * p_device_4; static struct platform_driver my_driver4 = { .driver = { .name = "xym-test-platform-device-4", }, .probe = my_platform_probe, .remove = my_platform_remove, .shutdown = my_platform_shutdown, .suspend = my_platform_suspend, .resume = my_platform_resume, }; static struct of_device_id oz1c007_match_table[] = { { .compatible = "dts_test"}, }; static struct platform_driver my_driver5 = { .driver = { .name = "xym-test-platform-device-5", .of_match_table = oz1c007_match_table, .owner = THIS_MODULE, }, .probe = my_platform_probe, .remove = my_platform_remove, .shutdown = my_platform_shutdown, .suspend = my_platform_suspend, .resume = my_platform_resume, }; static int platform_device_init(void) { int ret = 0; printk(KERN_INFO"%s\n",__func__); //device 1 ret = platform_device_register(&my_device1); if (ret) { printk(KERN_INFO"Unable to device 1 register(%d)\n", ret); return ret; } ret = platform_driver_register(&my_driver1); if (ret) { printk(KERN_INFO"Unable to driver 1 register(%d)\n", ret); return ret; } //device 2 p_device_2 = platform_device_register_full(&my_device_2); if (!p_device_2) { printk(KERN_INFO"Unable to device 2 register\n"); return ret; } ret = platform_driver_register(&my_driver2); if (ret) { printk(KERN_INFO"Unable to driver 2 register(%d)\n", ret); return ret; } //device 3 p_device_3 = platform_device_register_resndata(NULL, "xym-test-platform-device-3",-1,my_resoure3,ARRAY_SIZE(my_resoure3),&platform_data_3,sizeof(platform_data_3)); if (!p_device_3) { printk(KERN_INFO"Unable to device 3 register\n"); return ret; } ret = platform_driver_register(&my_driver3); if (ret) { printk(KERN_INFO"Unable to driver 4 register(%d)\n", ret); return ret; } //device 4 p_device_4 = platform_device_register_simple("xym-test-platform-device-4",-1,my_resoure4,ARRAY_SIZE(my_resoure4)); if (!p_device_4) { printk(KERN_INFO"Unable to device 4 register\n"); return ret; } platform_device_add_data(p_device_4, &platform_data_4,sizeof(platform_data_4)); ret = platform_driver_register(&my_driver4); if (ret) { printk(KERN_INFO"Unable to driver 4 register(%d)\n", ret); return ret; } //device 5 dts ret = platform_driver_register(&my_driver5); if (ret) { printk(KERN_INFO"Unable to driver 5 register(%d)\n", ret); return ret; } printk(KERN_INFO"---------------------------\n\n\n"); return ret; } static void platform_device_destory(void) { printk(KERN_INFO"%s\n",__func__); platform_device_unregister(p_device_1); platform_device_unregister(p_device_2); platform_device_unregister(p_device_3); platform_device_unregister(p_device_4); platform_driver_unregister(&my_driver1); platform_driver_unregister(&my_driver2); platform_driver_unregister(&my_driver3); platform_driver_unregister(&my_driver4); platform_driver_unregister(&my_driver5); } static int __init platform_test_init(void) { printk(KERN_INFO"Enter platform test\n\n"); platform_device_init(); return 0; } static void __exit platform_test_exit(void) { printk(KERN_INFO"Exit platform test\n"); platform_device_destory(); } module_init(platform_test_init); module_exit(platform_test_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marvin.xin"); MODULE_DESCRIPTION("A Test Module for Platform driver");
原文:https://www.cnblogs.com/forthetechnology/p/10647252.html