linux驱动之平台总线

平台总线platform_bus

1.内核定义的一个bus_type,还有其它的bus_type,以及自己都可以定义一个

在这里插入图片描述

2.platform_bus架构

  1. 架构图:
    在这里插入图片描述

  2. 原理:

    platform_bus下管理着两个链表一条是platform_device一条是platform_driver,如果有任何一边的注册了新的节点过来那么就会遍历另外的一条,根据名字进行匹配,如果匹配到了就执行probe,当devices从节点撤出就会执行其匹配的remove。

    driver下的name不能重复,而device下的name可以重复,也就是一个driver可以不用设备树就匹配多个devices

    具体可参考:

    [(81条消息) 手把手教Linux驱动10-platform总线详解_一口Linux的博客-CSDN博客]

3.简单驱动编写(不包含资源获取)

  1. device.c

    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/platform_device.h>
    
    void my_release(struct device *dev)
    {
    	printk("--------%s--------%s-----------%d-------\n",__FILE__,__FUNCTION__,__LINE__);
    	return;
    }
    
    static struct platform_device my_device=
    {
    	.name = "easy",
    	.id = -1,
    	.dev.release = my_release,//不写会报错
    	
    };
    static int __init my_device_init(void)
    {
    	printk("--------%s--------%s-----------%d-------\n",__FILE__,__FUNCTION__,__LINE__);
    	platform_device_register(&my_device);
    	return 0;
    }
    static void __exit my_device_exit(void)
    {
    	printk("--------%s--------%s-----------%d-------\n",__FILE__,__FUNCTION__,__LINE__);
    	platform_device_unregister(&my_device);
    	return;
    }
    module_init(my_device_init);
    module_exit(my_device_exit);
    MODULE_LICENSE("GPL");
    
  2. driver.c

    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/platform_device.h>
    
    
    int my_device_probe(struct platform_device *pdev)
    {
    	printk("--------%s--------%s-----------%d-------\n",__FILE__,__FUNCTION__,__LINE__);
    	return 0;
    }
    int my_device_remove(struct platform_device *pdev)
    {
    	printk("--------%s--------%s-----------%d-------\n",__FILE__,__FUNCTION__,__LINE__);
    	return 0;
    }
    
    static struct platform_driver my_driver=
    {
    	.probe = my_device_probe,
    	.remove = my_device_remove,
    	.driver.name = "easy",
    	
    };
    static int __init my_driver_init(void)
    {
    	printk("--------%s--------%s-----------%d-------\n",__FILE__,__FUNCTION__,__LINE__);
    	platform_driver_register(&my_driver);
    	return 0;
    }
    static void __exit my_driver_exit(void)
    {
    	printk("--------%s--------%s-----------%d-------\n",__FILE__,__FUNCTION__,__LINE__);
    	platform_driver_unregister(&my_driver);
    	return;
    }
    module_init(my_driver_init);
    module_exit(my_driver_exit);
    MODULE_LICENSE("GPL");
    
  3. 总结:

    1.在没设备树时可以通过.name = "easy",.driver.name = "easy",匹配
    static struct platform_device my_device=
    {
    	.name = "easy",
    	.id = -1,
    	.dev.release = my_release,//不写会报错
    	
    };
    static struct platform_driver my_driver=
    {
    	.probe = my_device_probe,
    	.remove = my_device_remove,
    	.driver.name = "easy",
    	
    };
    2.dev.release = my_release,//不写会报错
    3.my_release只有device remove才会执行,而my_device_remove二者remove都会执行。
    

4.获取资源

  1. deivce描述资源
    在这里插入图片描述

    1. flags:描述资源类型
      在这里插入图片描述
    2. start与end是u32的地址
  2. device.c改动

    static struct resource res[] = 
    {
    	[0] = {
    		.flags = IORESOURCE_MEM,
    		.start = 0x10000000,
    		.end = 0x10000000+0x3
    	},
    	[1] = {
    		.flags = IORESOURCE_IRQ,
    		.start = 66,
    		.end = 66,
    	}
    };
    
    static struct platform_device my_device=
    {
    	.name = "easy",
    	.id = -1,
    	.dev.release = my_release,//不写会报错
    	.num_resources = ARRAY_SIZE(res),
    	.resource = res,
    };
    
  3. driver.c改动

    int my_device_probe(struct platform_device *pdev)
    {
    	printk("--------%s--------%s-----------%d-------\n",__FILE__,__FUNCTION__,__LINE__);
    	printk("------%x--------\n",pdev->resource[0].start);//把资源打印出来
    	printk("------%d--------\n",pdev->resource[1].start);
    	return 0;
    }
    

5.设备树platform

1.driver.c

1.更改dts文件,添加一个或多个节点(记得要有compatible属性)
2.在driver中添加.of_match_table = &my_table    
static struct of_device_id my_table={
	.compatible = "myled",
};

static struct platform_driver mydri = {
	.driver		= {
		.name	= "hello_dev",
		.of_match_table = &my_table,
	},
	.probe		= my_probe,
	.remove 	= my_remove,
};

6.匹配原则

static int platform_match(struct device *dev, struct device_driver *drv)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct platform_driver *pdrv = to_platform_driver(drv);

	if (pdev->driver_override)
		return !strcmp(pdev->driver_override, drv->name);

	if (of_driver_match_device(dev, drv))
		return 1;

	if (acpi_driver_match_device(dev, drv))
		return 1;
	//优先通过设备树中断compitable与id_table的compitable匹配,一个driver可以匹配多个device
	if (pdrv->id_table)
		return platform_match_id(pdrv->id_table, pdev) != NULL;
	//最后才通过name匹配
	return (strcmp(pdev->name, drv->name) == 0);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值