文章目录
1 ID匹配
id匹配(可想象成八字匹配):一个驱动可以对应多个设备 ------在三种匹配方式中优先级次低。
注意事项:
1. device模块中,id的name成员必须与struct platform_device中的name成员内容一致,因此device模块中,structplatform_device中的name成员必须指定
2. driver模块中,struct platform_driver成员driver的name成员必须指定,但与device模块中name可以不相同
2 ID 匹配编写步骤
1 编写 xxx_device.c(设备)
1 在 platform_device xxxxxx中添加id_entry成员
struct platform_device fs4412led_device=
{
//用于名称匹配
.name="fs4412leds",
//设备回收时会被调用
.dev.release=fs4412led_dev_release,
.resource=fs4412led_dev_res,
//计算资源个数
.num_resources=ARRAY_SIZE(fs4412led_dev_res),
.id_entry=&fs4412leds_id,
};
2 编写 platform_device_id xxxxx
struct platform_device_id fs4412leds_id={
//注意和上面的name一致
.name="fs4412leds",
};
2 编写 xxx_driver.c(驱动)
1 在struct platform_driver xxxxx 中添加id_table成员
struct platform_driver fs4412leds_driver =
{
.driver.name="leds",
.probe=fs4412leds_driver_probe,
.remove=fs4412leds_driver_remove,
.id_table=fs4412leds_drv_ids,
};
2 编写struct platform_device_id xxxx_ids[]
struct platform_device_id fs4412leds_drv_ids[]={
[0]={
.name ="fs4412leds"},
[1]={
.name ="fs4412keys"},
[2]={
}//代表结束必须
};
3 led驱动id匹配版
3.1 fs4412_led.h
#ifndef MY_CHAR_H
#define MY_CHAR_H
#include <asm/ioctl.h>
#define LED_DEV_MAGIC 'g'
//#define MYCHAR_IOCTL_GET_MAXLEN _IOR(MY_CHAR_MAGIC,1,int*)
//#define MYCHAR_IOCTL_GET_CURLEN _IOR(MY_CHAR_MAGIC,2,int*)
#define MY_LED_OFF _IO(LED_DEV_MAGIC,0)
#define MY_LED_ON _IO(LED_DEV_MAGIC,1)
// led2
#define GPX2CON 0x11000C40
#define GPX2DAT 0x11000C44
// led3
#define GPX1CON 0x11000C20
#define GPX1DAT 0x11000C24
//led4,5
#define GPF3CON 0x114001E0
#define GPF3DAT 0x114001E4
#endif
3.2 fs4412leds_device.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include "fs4412_led.h"
//做清理工作
void fs4412led_dev_release(struct device *pdev)
{
printk("fs4412led_dev_release is called\n");
}
struct resource fs4412led_dev_res[]=
{
[0]={
.start=GPX1CON,.end=GPX1CON+3,.name="GPX1CON",.flags=IORESOURCE_MEM},
[1]={
.start=GPX1DAT,.end=GPX1DAT+3,.name="GPX1DAT",.flags=IORESOURCE_MEM},
[2]={
.start=GPX2CON,.end=GPX2CON+3,.name="GPX2CON",.flags=IORESOURCE_MEM},
[3]={
.start=GPX2DAT,.end=GPX2DAT+3,.name="GPX2DAT",.flags=IORESOURCE_MEM},
[4]={
.start=GPF3CON,.end=GPF3CON+3,.name="GPF3CON",.flags=IORESOURCE_MEM},
[5]={
.start=GPF3DAT,.end=GPF3DAT+3,.name="GPF3DAT",.flags=IORESOURCE_MEM},
};
struct platform_device_id fs4412leds_id={
//注意和下面的name一致
.name="fs4412leds",
};
struct platform_device fs4412led_device=
{
//用于名称匹配
.name="fs4412leds",
//设备回收时会被调用
.dev.release=fs4412led_dev_release,
.resource=fs4412led_dev_res,
//计算资源个数
.num_resources=ARRAY_SIZE(fs4412led_dev_res),
.id_entry=&fs4412leds_id,
};
int __init fs4412led_device_init(void)
{
platform_device_register(&fs4412led_device);
return 0;
}
void __exit fs4412led_device_exit(void)
{
platform_device_unregister(&fs4412led_device);
}
MODULE_LICENSE("GPL");
module_init(fs4412led_device_init);
module_exit(fs4412led_device_exit);
3.3 fs4412leds_driver.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/atomic.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include "fs4412_led.h"
#define fs4412leds_driver_DEV_CNT 1
int major =11;//主设备号
int minor = 0;//次设备号
int fs4412leds_driver_num =fs4412leds_driver_DEV_CNT;//设备数量
struct fs4412leds_driver_dev
{
struct cdev mydev;//建立一个设备对象
//volatile为不做优化
volatile unsigned long * led2con;
volatile unsigned long * led2dat;
volatile unsigned long * led3con;
volatile unsigned long * led3dat;
volatile unsigned long * led4con;
volatile unsigned long * led4dat;
volatile unsigned long * led5con;
volatile unsigned long * led5dat;
struct class *pcls;
struct device *pdev;
};
struct fs4412leds_driver_dev *gmydev_arr[fs4412leds_driver_DEV_CNT];
//打开
int fs4412leds_driver_open(struct inode *pnode,struct file *pfile)
{