A、PLATFORM驱动,虚拟总线的驱动。
1、写好设备树节点,中断,GPIO,别名等。
2、在驱动中新建 platform_driver结构体test_device_driver和of_device_id。注意:of_device_id必须多出一行空行。在platform_driver中写入probe和remove函数,以及和of_device_id绑定。
3、在INIT中调用register驱动的接口:platform_driver_register(&test_device_driver);,在该注册函数中,最总调用的会是结构体中的probe函数。
4、实现probe和remove函数。probe函数:probe(struct platform_device* pdev),
(1)、 match = of_match_device(siglentkb_dt_ids, &pdev->dev);匹配设备树中的别名节点。
(2)、 自定义一个结构体用以记录该驱动的全局变量。例如为test_dev。初始化test_dev = kmalloc(sizeof(struct siglentkb_dev_data), GFP_KERNEL);
(3)、调用of_iomap、platform_get_irq、devm_request_irq等函数从设备树中获取设备信息,并且注册中断处理函数。
(4)、建立create()函数用于创建设备号和class,device_class。a、file_operations siglentkb_fops 建立read,write..函数。b、调用register_chrdev函数动态获取设备号。c、调用class_create创建class记录在全部结构体test_dev中。d、调用device_create(test_dev->class, NULL, MKDEV(major, 0), NULL, "test");创建devcie下的设备。
(5)、实现中断处理函数。
B、I2C驱动。
1、写好设备树节点,注意硬件连线。将对于外设的描述记录在该节点上, 此处以GT911触摸屏为例。记录节点名:compatible = "goodix,gt9xx";设备地址:reg = <0x14>;复位及初始化管脚 <&gpio0 54 0x00>;
2、和上述PLATFORM类似,但是结构体不一样。此处需要建立i2c_driver结构体goodix_ts_driver和of_device_id。在i2c_driver中写入probe和remove函数,以及和of_device_id绑定。
3、在INIT函数中调用i2c_add_driver注册设备驱动。i2c_add_driver(&goodix_ts_driver);
4...步骤和platform注册类似。
注意:1、一般都会在probe中建立一个 wait_queue_head_t用以阻塞。一般调用函数 init_waitqueue_head(&inq);或者使用宏来初始化。使用wait_event_interruptible阻塞或者wake_up(&inq)函数调用。
2、一般都会建立一个自定义的驱动中的全局变量。用于数据共享使用。
3、不用总线驱动的注册函数不一样:I2C:i2c_add_driver。PLATFORM:platform_driver_register。不用函数中使用的结构体也不一致。platform_driver或者i2c_driver。但是内容结构是基本一致。
4、probe函数差别。
I2C:static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id),可以直接用client来操作read,write...函数
PLATFORM:static int test_probe(struct platform_device* pdev).