linux总线、设备和驱动

 Linux采用总线设备驱动模型。主要包含总线、设备、驱动三个部分。

总线:最先注册,有几个重要的回调函数,例如match函数用于匹配device和driver。
设备:设备的物理信息,例如设备名、物理地址、中断号等;
驱动:设备的驱动程序和设备名等信息,例如初始化函数、波特率设置函数、启动停止函数、中断函数等。

现实中,很多设备都是接在总线上的,例如SPI Flash接在SPI总线上,EEPROM接在I2C总线上。

但也有很多芯片内部设备没有挂在总线上,例如UART、SPI控制器。为了统一使用Linux总线设备驱动模型,内核中定义了一个虚拟总线 platform_bus_type,将这些设备(叫做平台设备)注册到该虚拟总线上统一管理。

Linux驱动注册顺序(总线、设备、驱动三者关系)

1、注册总线 xxx_bus_type:
在系统初始化阶段,会首先向内核注册各种常用的总线类型,比如pci, usb, spi, i2c, platform等等。

有两个重要的链表挂在bus上,一个是设备device链表,一个是驱动driver链表。
它包含的最关键的函数:match()用于匹配device和driver。

//例子:
static int __init spi_init(void)
{
	int	status;

printk("@@ spi_init :spi_bus_type\n");
	buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
	if (!buf) {
		status = -ENOMEM;
		goto err0;
	}

	status = bus_register(&spi_bus_type);
	if (status < 0)
		goto err1;

	status = class_register(&spi_master_class);
	if (status < 0)
		goto err2;
	return 0;

err2:
	bus_unregister(&spi_bus_type);
err1:
	kfree(buf);
	buf = NULL;
err0:
	return status;
}     

2、注册设备:将系统设备注册进内核的对应总线上,大多是调用xxx_device_regisger注册。
(xxx_device_regisger:将自己加到xxx总线的device链表,然后使用总线bus匹配对应的driver )

3、注册驱动:将系统设备的driver注册进内核的对应总线上:大多是调用xxx_drvier_register()注册。
(xxx_drvier_register:将自己加到xxx总线的driver链表,然后使用总线bus匹配对应的device )

2和3很多是在同一个函数中注册的,所以一起举例:

例子1:     
platform_driver_register(&uart_driver); //将uart的driver注册到platform_bus上;
platform_device_register(&uart_device); //将uart的device注册到platform_bus上;

例子2:
SPI Master控制器:drivers/spi/my_spi_master.c
platform_device_register(&dw_spi0_device); //注册device
platform_driver_probe(&dw_spi0_driver, dw_spi0_probe);  //1、注册driver
//2、spi_new_device子函数会注册SPI Flash的device到spi总线上;
//3、这里实现Master和Flash的绑定,即flash要使用哪个控制器控制;

例子3:
SPI Flash:drivers/mtd/gd25q_spi.c
spi_register_driver(&spi_flash_drv); //注册SPI Flash的driver到spi总线

上面几个例子的device和driver都成功注册后,对应总线的match回调函数会成功匹配driver和device,
并调用driver的probe函数完成设备初始化。

可以看到,不同设备的device和driver注册位置可能不同、注册顺序可能不同、注册函数名可能不同!!

4、设备和驱动的匹配:
老版内核的匹配大部分是看device和driver的name属性是否相同;新版使用设备树的内核中,是根据程序中driver的compatible 与设备树节点的compatible 是否相同来匹配!

match的工作是由总线(bus)来完成。

在xxx_device_register()或xxx_drvier_register(),即设备或驱动注册的时候,都会引发总线调用自己的match函数来寻找是否挂载有与该设备(或驱动)名字匹配的驱动(或设备);

如果只注册了设备或者只注册了驱动,总线会判定匹配失败,则暂时不会调用driver中的probe函数进行初始化等操作; 要等到设备、驱动都注册成功并匹配绑定后才会调用。

总线的一些概念

block:用于管理块设备,系统中的每一个块设备会在该目录下对应一个子目录。

bus:用于管理总线,没注册一条总线,在该目录下有一个对应的子目录。

其中,每个总线子目录下会有两个子目录:devices和drivers。

devices包含里系统中所有属于该总线的的设备。

drivers包含里系统中所有属于该总线的的驱动。

class:将系统中的设备按功能分类。

devices:该目录提供了系统中设备拓扑结构图。

dev:该目录已注册的设备节点的视图。

kernel:内核中的相关参数。

module:内核中的模块信息。

fireware:内核中的固件信息。

Fs:描述内核中的文件系统。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值