驱动层
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
int led_pdrv_probe(struct platform_device *pdev)//匹配成功之后调用这个函数,默认传参匹配成功之后的pdev
{
struct resource * addr_res1, *addr_res2;
struct resource * irq_res;
int irqno;
printk("---------------%s------------------\n",__FUNCTION__);
//获取平台资源
//参数1:pdev对象
//参数2:资源的类型
//参数3:资源的编号,同一种类型,从0开始编号
addr_res1 = platform_get_resource(pdev,IORESOURCE_MEM,0);
printk("addr_res1: start = 0x%x\n",addr_res1->start);
addr_res2 = platform_get_resource(pdev,IORESOURCE_MEM,1);
printk("addr_res2: start = 0x%x\n",addr_res2->start);
//方法一
irq_res = platform_get_resource(pdev,IORESOURCE_IRQ,0);
printk("irq_res: start = %d\n",irq_res->start);
printk("irq_res: end = %d\n",irq_res->end);
//方法二
irqno = platform_get_irq(pdev,0);
printk("irqno = %d\n",irqno); //获取的是中段资源的编号
return 0;
}
int led_pdrv_remove(struct platform_device *pdev)
{
printk("---------------%s------------------\n",__FUNCTION__);
return 0;
}
const struct platform_device_id led_id_table[] = {
{"s5pv210_led", 0x1122},
{"s3c2410_led", 0x1234},
{"s3c6410_led", 0x2233},
};
struct platform_driver led_pdrv = {
.probe = led_pdrv_probe,
.remove = led_pdrv_remove,
.driver = {
.name = "samsung led_drv",//自定义,但是一定要有,没有id_table则用这个名字和pdev匹配,--- ls /sys/bus/platform/drivers/下创建同名目录
},
.id_table = led_id_table,
};
static int __init led_pdrv_init(void)
{
printk("--------------%s--------------\n",__FUNCTION__);
return platform_driver_register(&led_pdrv);
}
static void __exit led_pdrv_exit(void)
{
printk("--------------%s--------------\n",__FUNCTION__);
platform_driver_unregister(&led_pdrv);
}
module_init(led_pdrv_init);
module_exit(led_pdrv_exit);
MODULE_LICENSE("GPL");
设备层
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#define LED_GPC0_CONF 0xe0200060
#define LED_GPC0_SIZE 8
struct resource led_resource[] = {
[0] = {
.start = LED_GPC0_CONF,
.end = LED_GPC0_CONF + LED_GPC0_SIZE - 1,
.flags = IORESOURCE_MEM,
},
//以下是演示代码
[1] = {
.start = 0x1122,
.end = 0x1122,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = 0xe0200160,
.end = 0xe0200160 + 8 - 1,
.flags = IORESOURCE_MEM,
},
};
//可以不用实现5,但是一定要有,因为卸载的时候会调用
void led_pdev_release(struct device *dev)
{
printk("--------------%s--------------\n",__FUNCTION__);
}
struct platform_device led_pdev = {
.name = "s5pv210_led",
.id = -1,
.dev = {
.release = led_pdev_release,
},
.num_resources = ARRAY_SIZE(led_resource),
.resource = led_resource,
};
static int __init led_pdev_init(void)
{
printk("--------------%s--------------\n",__FUNCTION__);
return platform_device_register(&led_pdev);
}
static void __exit led_pdev_exit(void)
{
printk("--------------%s--------------\n",__FUNCTION__);
platform_device_unregister(&led_pdev);
}
module_init(led_pdev_init);
module_exit(led_pdev_exit);
MODULE_LICENSE("GPL");
驱动装载顺序无要求,都会先执行init函数,第二个驱动装载完成后,两者会进行匹配,匹配成功后执行probe方法。
装载过程如下:
①
[root@farsight /drv_module]# insmod plat_led_dev.ko
--------------led_pdev_init--------------
[root@farsight /drv_module]# insmod plat_led_drv.ko
--------------led_pdrv_init--------------
---------------led_pdrv_probe------------------
addr_res1: start = 0xe0200060
addr_res2: start = 0xe0200160
irq_res: start = 4386
irq_res: end = 4386
irqno = 4386
②
[root@farsight /drv_module]# insmod plat_led_drv.ko
--------------led_pdrv_init--------------
[root@farsight /drv_module]# insmod plat_led_dev.ko
--------------led_pdev_init--------------
---------------led_pdrv_probe------------------
addr_res1: start = 0xe0200060
addr_res2: start = 0xe0200160
irq_res: start = 4386
irq_res: end = 4386
irqno = 4386
卸载过程要按照顺序
[root@farsight /drv_module]# rmmod plat_led_dev
--------------led_pdev_exit--------------
---------------led_pdrv_remove------------------
--------------led_pdev_release--------------
[root@farsight /drv_module]# rmmod plat_led_drv
--------------led_pdrv_exit--------------