fsjack 发表于 2011-03-09 17:04

Led驱动Platform设备注册后无法调用probe函数

做了个简单的led驱动,网上和书上都说device和driver注册后,如果name匹配的话就会调用probe进行加载,可是当我注册了device和driver后没有调用probe,不知道为什么,请各位大大帮忙看看,感激不尽!:)

led.h#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/hardware.h>
#include <asm/hardware.h>
#include <asm/delay.h>

#define LED_MINOR 0
#define LED_DRIVER "Led Driver For Test"
#define DEV_NAME "LED"

static int led_open (struct inode *node, struct file *filp);
static int led_ioctl (struct inode *node, struct file *filp, unsigned int cmd, unsigned long arg);
static ssize_t led_write (struct file *filp, const char __user *buf, size_t count, loff_t *f_ops);
static int led_probe(struct device * dev);
static int led_remove(struct device * dev);
static int led_release (struct inode *node, struct file *filp);

static struct file_operations led_fops = {
    .owner=   THIS_MODULE,
    .open   =   led_open,
    .write=   led_write,
    .ioctl=   led_ioctl,
    .release    =   led_release,
};

static struct miscdevice led_miscdev = {
    MISC_DYNAMIC_MINOR,
    DEV_NAME,
    &led_fops,
};

struct platform_device *led_dev;
static struct device_driver led_driver = {
    .name   =   DEV_NAME,
    .bus    =   &platform_bus_type,
    .probe=   led_probe,
    .remove =   led_remove,
};

static unsigned long led_table[] = {
    S3C2410_GPF4,
    S3C2410_GPF5,
    S3C2410_GPF6,
    S3C2410_GPF7,
};

static unsigned long led_cfg_table[] = {
    S3C2410_GPF4_OUTP,
    S3C2410_GPF5_OUTP,
    S3C2410_GPF6_OUTP,
    S3C2410_GPF7_OUTP,
};


led.c#include "led.h"

static void led_on_off(int led_num,int led_on_off){
    //1 for on,2 for off
    if (led_num>ARRAY_SIZE(led_table)-1)
      return;

    s3c2410_gpio_setpin(led_table,led_on_off );
}

static void all_led_on(void){
    int i;
    for(i=0;i<ARRAY_SIZE(led_table);i++){
      s3c2410_gpio_setpin(led_table,0);
    }
}

static void all_led_out(void){
    int i;
    for(i=0;i<ARRAY_SIZE(led_table);i++){
      s3c2410_gpio_setpin(led_table,1);
    }
}

static void leds_init(void){
    int i;
    for(i=0;i<ARRAY_SIZE(led_table);i++){
      s3c2410_gpio_cfgpin(led_table,led_cfg_table);
    }
}
   

static ssize_t led_write (struct file *filp, const char __user *buf, size_t count, loff_t *f_ops){
    return 0;
}

static int led_ioctl (struct inode *node, struct file *filp, unsigned int cmd, unsigned long arg){
    return 0;
}


static int led_open (struct inode *node, struct file *filp){
    printk("led driver is opened.\n");
    return 0;
}

static int led_release (struct inode *node, struct file *filp){
    printk("led driver is closed.\n");
    return 0;
}

static int led_probe(struct device * dev){
    misc_register(&led_miscdev);
    printk("%s is installed.\n",LED_DRIVER);

    all_led_on();
   
    printk("%s probe!\n",DEV_NAME);
    return 0;
}

static int led_remove(struct device * dev){
    all_led_out();
   
    if(misc_deregister(&led_miscdev))
      printk("misc device is deregister!\n");

    printk("%s remove!\n",DEV_NAME);
    return 0;
}

static int __init led_init(void){
    int ret;

    led_dev = platform_device_register_simple(DEV_NAME,-1,NULL,0);
    if(IS_ERR(led_dev)){
      printk("failed to register device %s",DEV_NAME);
      return -EINVAL;
    }
    printk("Device is sucessfully registered.\n");

    ret = driver_register(&led_driver);
    if(ret){
      platform_device_unregister(led_dev);
      printk("failed to register driver %s",LED_DRIVER);
      return -EINVAL;
    }
    printk("Driver is sucessfully registered.\n");


    leds_init();
    return 0;
}

static void __exit led_exit(void){
    driver_unregister(&led_driver);
    platform_device_unregister(led_dev);

    printk("led modules exit!\n");
}


module_init(led_init);
module_exit(led_exit);

MODULE_AUTHOR("Jackie Cheung");
MODULE_LICENSE("GPL");

fsjack 发表于 2011-03-09 19:00

顶上去~!:roll:

amarant 发表于 2011-03-10 08:32

对着例子模仿下吧,要不多加点printk看看跑了哪些,多调一下就明白了~

(不愿仔细看代码,:lol::lol:)

jn200002 发表于 2011-03-10 12:59

你从内核拷贝个led.c的驱动,然后把所有的都删掉。


然后留下注册,和probe然后一步一步加你想要的功能.


不愿意这样做,你可以在你所有的函数里加printk,像这样贴一篇代码上来,大多数人只看个驱动名称,是led,愿意再看的就几乎没有了。

lemin9538 发表于 2011-03-10 15:24

我觉得你应该用platform_driver_register()注册相对应的平台驱动结构体,使他们属于platform总线下。而不是driver_register(),使用driver_register()后他们不是属于同一总线下,是不会匹配的吧?

Trigger_Huang 发表于 2011-03-10 15:53

首先,你应该定义的是struct platform_device 结构体对象,而不是指针,并把把它的name赋值
其次你应该定义的是   struct platform_driver 结构体对象,而不是device_driver的对象,且要对其中的.driver.name赋值一样的名字,或者为id_table赋值。
第三,应该是在init函数中用platform_device_register以及platform_driver_register进行注册。device和device_driver只是虚基类,一般不会直接引用的,像platform, PCI USB等都是继承的该类。

Trigger_Huang 发表于 2011-03-10 15:55

而且最好将device和driver分开编写成两个模块,然后先insmod device 然后再insmod driver。写在一起的这种做法貌似不是很推荐。

whjzbp 发表于 2011-03-11 10:53

如果是arm核的话,那要在/arch/arm/mach-xxxx/devs.c中添加struct platform_devicemy_device_led,, 然后在/arch/arm/mach-xxxx/mach-xxxx.c中的static struct platform_device *smdkxxx_devices[] __initdata = {中添加&my_device_led

请参考可以否

jounehou 发表于 2011-03-11 13:08

看来楼主的麻烦还是比较多的 。。最好多加点打印信息哦。。看走到哪里去了。还有 我不明白的是 楼主是把这个驱动编译成模块的 还是直接编进内核的呢?

fsjack 发表于 2011-03-11 13:41

非常感谢各位!
原来Linux设备模型只适用于编译进内核么?就是说platform_device和platform_driver的形式来写驱动不适用于编译成模块再insmod加载?

另外我用的是FS2410开发板,预装Linux2.6.8,所以我懒得移植新版内核就用这个了,而这个内核是没有Platform_driver的,所以就用device_driver了。
页: [1] 2
查看完整版本: Led驱动Platform设备注册后无法调用probe函数