platform总线驱动

来源:互联网 发布:mui案例源码下载 编辑:程序博客网 时间:2024/06/06 19:11

在上一篇LED驱动中,设备与驱动是挂在总线上,通过总线上的macth(Linux系统总线添加设备或驱动时调用各总线对应的match匹配函数判断驱动和设备是否匹配)进行设备与驱动的匹配,本篇一起学习另一种总线,platform,平台总线,一种虚拟总线,使板子代码与驱动代码分离,使驱动有更好的可扩展性和跨平台性。


platform总线相应的设备称为platform_device,驱动为platform_driver。

我们要实现的还是设备与驱动的注册与匹配,匹配成功之后调用probe函数,probe函数完成驱动注册最后工作,资源,中断调用函数以及其他相关工作。


接下来就分析一下我们的具体代码

1.platform设备与驱动的定义

  1. static struct platform_device s3c_led_device = {  
  2.      .name    = "s3c_led",  
  3.      .id      = 1,  
  4.      .dev     =  
  5.      {  
  6.          .platform_data = &s3c_led_data,  
  7.          .release = platform_led_release,  
  8.      },  
  9.  };  

[cpp] view plain copy
 print?
  1. static struct platform_driver s3c_led_driver = {  
  2.      .probe      = s3c_led_probe,  
  3.      .remove     = s3c_led_remove,  
  4.      .driver     = {  
  5.          .name       = "s3c_led",  
  6.          .owner      = THIS_MODULE,  
  7.      },  
  8.  };  

这里可以看见我们的.name是一样的,这样才能匹配成功,才能绑定在一起。

2.platform平台设备与驱动的注册

  1. static int __init s3c_led_init(void)  
  2.  {  
  3.     int       ret = 0;  
  4.    
  5.     ret = platform_device_register(&s3c_led_device);     //注册平台设备  
  6.     if(ret)  
  7.     {  
  8.          printk(KERN_ERR "%s:%d: Can't register platform device %d\n", __FUNCTION__,__LINE__, ret);  
  9.          goto fail_reg_plat_dev;  
  10.     }  
  11.     dbg_print("Regist S3C LED Platform Device successfully.\n");  
  12.    
  13.     ret = platform_driver_register(&s3c_led_driver);     //注册平台驱动  
  14.     if(ret)  
  15.     {  
  16.         printk(KERN_ERR "%s:%d: Can't register platform driver %d\n", __FUNCTION__,__LINE__, ret);  
  17.         goto fail_reg_plat_drv;  
  18.     }  
  19.     dbg_print("Regist S3C LED Platform Driver successfully.\n");  
  20.    
  21.     return 0;  
  22.   
  23.  fail_reg_plat_drv:  
  24.     platform_driver_unregister(&s3c_led_driver);  
  25.  fail_reg_plat_dev:  
  26.     return ret;  
  27.  }  

注册的工作就是由init来完成,即一启动便注册。我们可以看到,注册平台设备和平台驱动时,分别取sc3_led_device和s3c_led_driver结构体的值,也就是我们刚才定义的platform设备与驱动结构体。

3.当驱动与设备的.name匹配成功后,我们的probe也该出来做媒了。

  1. static int s3c_led_probe(struct platform_device *dev)  
  2.  {  
  3.      struct s3c_led_platform_data *pdata = dev->dev.platform_data;  
  4.      int result = 0;  
  5.      int i;  
  6.      dev_t devno;  
  7.       
  8.     /* Initialize the LED status 对LED状态的初始化*/  
  9.      for(i=0; i<pdata->nleds; i++)  
  10.      {  
  11.           s3c2410_gpio_cfgpin(pdata->leds[i].gpio, S3C2410_GPIO_OUTPUT);  
  12.           if(ON == pdata->leds[i].status)  
  13.           {  
  14.              s3c2410_gpio_setpin(pdata->leds[i].gpio, pdata->leds[i].active_level);  //将输出值存在active_level中  
  15.           }  
  16.           else  
  17.           {  
  18.              s3c2410_gpio_setpin(pdata->leds[i].gpio, ~pdata->leds[i].active_level);   
  19.           }  
  20.      }  
  21.        
  22.       
  23.     /*  Alloc the device for driver 申请设备号*/  
  24.      if (0 != dev_major)  
  25.      {  
  26.          devno = MKDEV(dev_major, dev_minor);  
  27.          result = register_chrdev_region(devno, 1, DEV_NAME);  
  28.      }  
  29.      else  
  30.      {  
  31.          result = alloc_chrdev_region(&devno, dev_minor, 1, DEV_NAME);  
  32.          dev_major = MAJOR(devno);  
  33.      }  
  34.    
  35.    
  36.      /* Alloc for device major failure */  
  37.      if (result < 0)  
  38.      {  
  39.          printk("%s driver can't get major %d\n", DEV_NAME, dev_major);  
  40.          return result;  
  41.      }  
  42.   
  43.        
  44.     /* Initialize button structure and register cdev*/  
  45.      memset(&led_device, 0, sizeof(led_device));         //memset函数初始化内存  
  46.      led_device.data = dev->dev.platform_data;  
  47.      cdev_init (&(led_device.cdev), &led_fops);        //初始化字符设备cdev  
  48.      led_device.cdev.owner  = THIS_MODULE;  
  49.    
  50.      result = cdev_add (&(led_device.cdev), devno , 1);       //注册字符设备cdev  
  51.      if (result)  
  52.      {  
  53.          printk (KERN_NOTICE "error %d add %s device", result, DEV_NAME);  
  54.          goto ERROR;  
  55.      }  
  56.   
  57.     led_device.dev_class = class_create(THIS_MODULE, DEV_NAME);      //定义一个类来自动创建设备节点,我们在测试程序时就不用再自己创建了。  
  58.      if(IS_ERR(led_device.dev_class))  
  59.      {  
  60.          printk("%s driver create class failture\n",DEV_NAME);  
  61.          result =  -ENOMEM;  
  62.          goto ERROR;  
  63.      }  
  64.    
  65.  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)       
  66.      device_create(led_device.dev_class, NULL, devno, NULL, DEV_NAME);  
  67.  #else  
  68.      device_create (led_device.dev_class, NULL, devno, DEV_NAME);  
  69.  #endif  
  70.   
  71.      /*  Initial the LED blink timer 初始化闪烁时间,这个timer函数在下面介绍*/  
  72.      init_timer(&(led_device.blink_timer));  
  73.      led_device.blink_timer.function = led_timer_handler;  
  74.      led_device.blink_timer.data = (unsigned long)pdata;  
  75.      led_device.blink_timer.expires  = jiffies + TIMER_TIMEOUT;  
  76.      add_timer(&(led_device.blink_timer));  
  77.    
  78.      printk("S3C %s driver version %d.%d.%d initiliazed.\n", DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);  
  79.    
  80.      return 0;  
  81.    
  82.    
  83.  ERROR:  
  84.      printk("S3C %s driver version %d.%d.%d install failure.\n", DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER,DRV_REVER_VER);  
  85.      cdev_del(&(led_device.cdev));  
  86.    
  87.      unregister_chrdev_region(devno, 1);  
  88.      return result;  
  89.    
  90.  }  

probe函数主要完成了申请设备号,初始化和注册字符设备cdev,从cdev读出硬件资源。


4.重要的结构体:

  1. static struct file_operations led_fops = {  
  2.      .owner = THIS_MODULE,  
  3.      .open = led_open,  
  4.      .release = led_release,  
  5.      .unlocked_ioctl = led_ioctl, /* compatible with kernel version >=2.6.38*/  
  6.  };  

这个结构体说明了我们要用到的一些函数调用,我们的读写操作都要经过这里才能实现。

5.led_timer_handler函数

  1. void led_timer_handler(unsigned long data)  
  2.  {  
  3.      int  i;  
  4.      struct s3c_led_platform_data *pdata = (struct s3c_led_platform_data *)data;  
  5.    
  6.      for(i=0; i<pdata->nleds; i++)  
  7.      {  
  8.          if(ON == pdata->leds[i].status)  
  9.          {  
  10.                s3c2410_gpio_setpin(pdata->leds[i].gpio, pdata->leds[i].active_level);  
  11.          }  
  12.          else  
  13.          {  
  14.                s3c2410_gpio_setpin(pdata->leds[i].gpio, ~pdata->leds[i].active_level);  
  15.          }  
  16.    
  17.          if(ENABLE == pdata->leds[i].blink )  /* LED should blink */  
  18.          {  
  19.              /* Switch status between 0 and 1 to turn LED ON or off */  
  20.              pdata->leds[i].status = pdata->leds[i].status ^ 0x01;  
  21.          }<pre class="cpp" name="code">         mod_timer(&(led_device.blink_timer), jiffies + TIMER_TIMEOUT);  //如果有blink,即闪烁属性,则每个循环改变一次状态。  
  22.      }  
  23.  }  
  24. </pre><br>  
  25. <pre></pre>  
  26. <p>这个函数定时读取每个LED引脚的状态存到active_level中。</p>  
  27. <p></p>  
  28. <p>好了,几个主要的函数已经分析完了,还有一些函数调用以及结构体的定义我们给一篇完整的驱动代码:</p>  
  29. <pre class="cpp" name="code">/********************************************************************************* 
  30.  *      Copyright:  (C) 2017 Tang Yanjun<519656780@qq.com>   
  31.  *                  All rights reserved. 
  32.  * 
  33.  *       Filename:  s3c_led.c 
  34.  *    Description:  This is the common LED driver runs on S3C24XX. 
  35.  *                  
  36.  *        Version:  1.0.0(10/27/2011~) 
  37.  *         Author:  Tang Yanjun <519656780@qq.com> 
  38.  *      ChangeLog:  1, Release initial version on "23/4/2017 11:39:10 AM" 
  39.  *                  
  40.  ********************************************************************************/  
  41. #include "s3c_driver.h"  
  42.   
  43. #define DRV_AUTHOR                "Tang Yanjun <519656780@qq.com>"  
  44. #define DRV_DESC                  "S3C24XX LED driver"  
  45.   
  46. /* Driver version*/  
  47. #define DRV_MAJOR_VER             1  
  48. #define DRV_MINOR_VER             0  
  49. #define DRV_REVER_VER             0  
  50.   
  51. #define DEV_NAME                  DEV_LED_NAME  
  52.   
  53. #define DEV_MAJOR                 DEV_LED_MAJOR  
  54. #ifndef DEV_MAJOR  
  55. #define DEV_MAJOR                 0 /*  dynamic major by default */   
  56. #endif  
  57.   
  58. #define TIMER_TIMEOUT             40  
  59.   
  60. static int debug = DISABLE;  
  61. static int dev_major = DEV_MAJOR;  
  62. static int dev_minor = 0;  
  63.   
  64.   
  65. /* ============================ Platform Device part ===============================*/  
  66. /*  LED hardware informtation structure*/  
  67. struct s3c_led_info  
  68. {  
  69.     unsigned char           num;              /* The LED number  */  
  70.     unsigned int            gpio;             /* Which GPIO the LED used */    
  71.     unsigned char           active_level;     /* The GPIO pin level(HIGHLEVEL or LOWLEVEL) to turn on or off  */  
  72.     unsigned char           status;           /* Current LED status: OFF/ON */  
  73.     unsigned char           blink;            /* Blink or not */             
  74. };  
  75.   
  76. /*  The LED platform device private data structure */  
  77. struct s3c_led_platform_data  
  78. {  
  79.     struct s3c_led_info    *leds;  
  80.     int                     nleds;  
  81. };  
  82.   
  83.   
  84. /*  LED hardware informtation data*/   
  85. static struct s3c_led_info  s3c_leds[] = {  
  86.     [0] = {  
  87.         .num = 1,  
  88.         .gpio = S3C2410_GPB(5),  
  89.         .active_level = LOWLEVEL,  
  90.         .status = OFF,  
  91.         .blink = ENABLE,  
  92.     },  
  93.     [1] = {  
  94.         .num = 2,  
  95.         .gpio = S3C2410_GPB(6),  
  96.         .active_level = LOWLEVEL,  
  97.         .status = OFF,  
  98.         .blink = DISABLE,  
  99.     },  
  100.     [2] = {  
  101.         .num = 3,  
  102.         .gpio = S3C2410_GPB(8),  
  103.         .active_level = LOWLEVEL,  
  104.         .status = OFF,  
  105.         .blink = DISABLE,  
  106.     },  
  107.     [3] = {   
  108.         .num = 4,  
  109.         .gpio = S3C2410_GPB(10),  
  110.         .active_level = LOWLEVEL,  
  111.         .status = OFF,  
  112.         .blink = DISABLE,  
  113.     },   
  114. };  
  115.   
  116. /*  The LED platform device private data */  
  117. static struct s3c_led_platform_data s3c_led_data = {  
  118.     .leds = s3c_leds,  
  119.     .nleds = ARRAY_SIZE(s3c_leds),  
  120. };  
  121.   
  122. struct led_device  
  123. {  
  124.     struct s3c_led_platform_data    *data;  
  125.     struct cdev                     cdev;  
  126.     struct class                    *dev_class;  
  127.     struct timer_list               blink_timer;  
  128. } led_device;  
  129.   
  130. static void platform_led_release(struct device * dev)  
  131. {  
  132.     int i;  
  133.     struct s3c_led_platform_data *pdata = dev->platform_data;   
  134.   
  135.     dbg_print("%s():%d\n", __FUNCTION__,__LINE__);  
  136.   
  137.     /* Turn all LED off */  
  138.     for(i=0; i<pdata->nleds; i++)  
  139.     {  
  140.          s3c2410_gpio_setpin(pdata->leds[i].gpio, ~pdata->leds[i].active_level);   
  141.     }  
  142. }  
  143.   
  144. static struct platform_device s3c_led_device = {  
  145.     .name    = "s3c_led",  
  146.     .id      = 1,  
  147.     .dev     =   
  148.     {  
  149.         .platform_data = &s3c_led_data,   
  150.         .release = platform_led_release,  
  151.     },  
  152. };  
  153.   
  154.   
  155.   
  156. /* ===================== led device driver part ===========================*/  
  157.   
  158. void led_timer_handler(unsigned long data)  
  159. {   
  160.     int  i;   
  161.     struct s3c_led_platform_data *pdata = (struct s3c_led_platform_data *)data;  
  162.   
  163.     for(i=0; i<pdata->nleds; i++)   
  164.     {   
  165.         if(ON == pdata->leds[i].status)  
  166.         {  
  167.               s3c2410_gpio_setpin(pdata->leds[i].gpio, pdata->leds[i].active_level);   
  168.         }  
  169.         else  
  170.         {  
  171.               s3c2410_gpio_setpin(pdata->leds[i].gpio, ~pdata->leds[i].active_level);   
  172.         }  
  173.   
  174.         if(ENABLE == pdata->leds[i].blink )  /* LED should blink */  
  175.         {  
  176.             /* Switch status between 0 and 1 to turn LED ON or off */  
  177.             pdata->leds[i].status = pdata->leds[i].status ^ 0x01;    
  178.         }  
  179.   
  180.         mod_timer(&(led_device.blink_timer), jiffies + TIMER_TIMEOUT);  
  181.     }  
  182. }  
  183.   
  184.   
  185. static int led_open(struct inode *inode, struct file *file)  
  186. {   
  187.     struct led_device *pdev ;  
  188.     struct s3c_led_platform_data *pdata;  
  189.   
  190.     pdev = container_of(inode->i_cdev,struct led_device, cdev);  
  191.     pdata = pdev->data;  
  192.   
  193.     file->private_data = pdata;  
  194.   
  195.     return 0;  
  196. }  
  197.   
  198.   
  199. static int led_release(struct inode *inode, struct file *file)  
  200. {   
  201.     return 0;  
  202. }  
  203.   
  204. static void print_led_help(void)  
  205. {  
  206.     printk("Follow is the ioctl() command for LED driver:\n");  
  207.     printk("Enable Driver debug command: %u\n", SET_DRV_DEBUG);  
  208.     printk("Get Driver verion  command : %u\n", GET_DRV_VER);  
  209.     printk("Turn LED on command        : %u\n", LED_ON);  
  210.     printk("Turn LED off command       : %u\n", LED_OFF);  
  211.     printk("Turn LED blink command     : %u\n", LED_BLINK);  
  212. }  
  213.   
  214. /* compatible with kernel version >=2.6.38*/  
  215. static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  
  216. {   
  217.     struct s3c_led_platform_data *pdata = file->private_data;  
  218.   
  219.     switch (cmd)  
  220.     {  
  221.         case SET_DRV_DEBUG:  
  222.             dbg_print("%s driver debug now.\n", DISABLE == arg ? "Disable" : "Enable");  
  223.             debug = (0==arg) ? DISABLE : ENABLE;  
  224.             break;  
  225.         case GET_DRV_VER:  
  226.             print_version(DRV_VERSION);  
  227.             return DRV_VERSION;  
  228.   
  229.         case LED_OFF:  
  230.             if(pdata->nleds <= arg)  
  231.             {  
  232.                printk("LED%ld doesn't exist\n", arg);    
  233.                return -ENOTTY;  
  234.             }  
  235.             pdata->leds[arg].status = OFF;  
  236.             pdata->leds[arg].blink = DISABLE;  
  237.             break;  
  238.   
  239.         case LED_ON:  
  240.             if(pdata->nleds <= arg)  
  241.             {  
  242.                printk("LED%ld doesn't exist\n", arg);    
  243.                return -ENOTTY;  
  244.             }  
  245.             pdata->leds[arg].status = ON;  
  246.             pdata->leds[arg].blink = DISABLE;  
  247.             break;  
  248.   
  249.         case LED_BLINK:  
  250.             if(pdata->nleds <= arg)  
  251.             {  
  252.                printk("LED%ld doesn't exist\n", arg);    
  253.                return -ENOTTY;  
  254.             }  
  255.             pdata->leds[arg].blink = ENABLE;  
  256.             pdata->leds[arg].status = ON;  
  257.             break;  
  258.   
  259.         default:   
  260.             dbg_print("%s driver don't support ioctl command=%d\n", DEV_NAME, cmd);   
  261.             print_led_help();  
  262.             return -EINVAL;  
  263.   
  264.     }  
  265.     return 0;  
  266. }  
  267.   
  268.   
  269. static struct file_operations led_fops = {   
  270.     .owner = THIS_MODULE,   
  271.     .open = led_open,   
  272.     .release = led_release,   
  273.     .unlocked_ioctl = led_ioctl, /* compatible with kernel version >=2.6.38*/  
  274. };  
  275.   
  276.   
  277. static int s3c_led_probe(struct platform_device *dev)  
  278. {  
  279.     struct s3c_led_platform_data *pdata = dev->dev.platform_data;   
  280.     int result = 0;  
  281.     int i;  
  282.     dev_t devno;  
  283.   
  284.     /* Initialize the LED status */  
  285.     for(i=0; i<pdata->nleds; i++)  
  286.     {  
  287.          s3c2410_gpio_cfgpin(pdata->leds[i].gpio, S3C2410_GPIO_OUTPUT);  
  288.          if(ON == pdata->leds[i].status)  
  289.          {  
  290.             s3c2410_gpio_setpin(pdata->leds[i].gpio, pdata->leds[i].active_level);   
  291.          }  
  292.          else  
  293.          {  
  294.             s3c2410_gpio_setpin(pdata->leds[i].gpio, ~pdata->leds[i].active_level);   
  295.          }  
  296.     }  
  297.   
  298.     /*  Alloc the device for driver */  
  299.     if (0 != dev_major)   
  300.     {   
  301.         devno = MKDEV(dev_major, dev_minor);   
  302.         result = register_chrdev_region(devno, 1, DEV_NAME);   
  303.     }   
  304.     else   
  305.     {   
  306.         result = alloc_chrdev_region(&devno, dev_minor, 1, DEV_NAME);   
  307.         dev_major = MAJOR(devno);   
  308.     }  
  309.   
  310.     /* Alloc for device major failure */   
  311.     if (result < 0)   
  312.     {   
  313.         printk("%s driver can't get major %d\n", DEV_NAME, dev_major);   
  314.         return result;   
  315.     }  
  316.   
  317.     /* Initialize button structure and register cdev*/  
  318.     memset(&led_device, 0, sizeof(led_device));  
  319.     led_device.data = dev->dev.platform_data;  
  320.     cdev_init (&(led_device.cdev), &led_fops);  
  321.     led_device.cdev.owner  = THIS_MODULE;  
  322.   
  323.     result = cdev_add (&(led_device.cdev), devno , 1);   
  324.     if (result)   
  325.     {   
  326.         printk (KERN_NOTICE "error %d add %s device", result, DEV_NAME);   
  327.         goto ERROR;   
  328.     }   
  329.       
  330.     led_device.dev_class = class_create(THIS_MODULE, DEV_NAME);   
  331.     if(IS_ERR(led_device.dev_class))   
  332.     {   
  333.         printk("%s driver create class failture\n",DEV_NAME);   
  334.         result =  -ENOMEM;   
  335.         goto ERROR;   
  336.     }  
  337.   
  338. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)       
  339.     device_create(led_device.dev_class, NULL, devno, NULL, DEV_NAME);  
  340. #else  
  341.     device_create (led_device.dev_class, NULL, devno, DEV_NAME);  
  342. #endif  
  343.   
  344.     /*  Initial the LED blink timer */  
  345.     init_timer(&(led_device.blink_timer));  
  346.     led_device.blink_timer.function = led_timer_handler;  
  347.     led_device.blink_timer.data = (unsigned long)pdata;  
  348.     led_device.blink_timer.expires  = jiffies + TIMER_TIMEOUT;  
  349.     add_timer(&(led_device.blink_timer));   
  350.   
  351.     printk("S3C %s driver version %d.%d.%d initiliazed.\n", DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);   
  352.   
  353.     return 0;  
  354.                  
  355.   
  356. ERROR:   
  357.     printk("S3C %s driver version %d.%d.%d install failure.\n", DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER, DRV_REVER_VER);   
  358.     cdev_del(&(led_device.cdev));   
  359.   
  360.     unregister_chrdev_region(devno, 1);   
  361.     return result;  
  362.   
  363. }  
  364.   
  365. static int s3c_led_remove(struct platform_device *dev)  
  366. {  
  367.     dev_t devno = MKDEV(dev_major, dev_minor);  
  368.   
  369.     del_timer(&(led_device.blink_timer));  
  370.   
  371.     cdev_del(&(led_device.cdev));   
  372.     device_destroy(led_device.dev_class, devno);   
  373.     class_destroy(led_device.dev_class);   
  374.       
  375.     unregister_chrdev_region(devno, 1);   
  376.     printk("S3C %s driver removed\n", DEV_NAME);  
  377.   
  378.     return 0;  
  379. }  
  380.   
  381.   
  382. static struct platform_driver s3c_led_driver = {   
  383.     .probe      = s3c_led_probe,   
  384.     .remove     = s3c_led_remove,   
  385.     .driver     = {   
  386.         .name       = "s3c_led",   
  387.         .owner      = THIS_MODULE,   
  388.     },  
  389. };  
  390.   
  391.   
  392. static int __init s3c_led_init(void)  
  393. {  
  394.    int       ret = 0;  
  395.   
  396.    ret = platform_device_register(&s3c_led_device);  
  397.    if(ret)  
  398.    {  
  399.         printk(KERN_ERR "%s:%d: Can't register platform device %d\n", __FUNCTION__,__LINE__, ret);   
  400.         goto fail_reg_plat_dev;  
  401.    }  
  402.    dbg_print("Regist S3C LED Platform Device successfully.\n");  
  403.   
  404.    ret = platform_driver_register(&s3c_led_driver);  
  405.    if(ret)  
  406.    {  
  407.         printk(KERN_ERR "%s:%d: Can't register platform driver %d\n", __FUNCTION__,__LINE__, ret);   
  408.         goto fail_reg_plat_drv;  
  409.    }  
  410.    dbg_print("Regist S3C LED Platform Driver successfully.\n");  
  411.   
  412.    return 0;  
  413.   
  414. fail_reg_plat_drv:  
  415.    platform_driver_unregister(&s3c_led_driver);  
  416. fail_reg_plat_dev:  
  417.    return ret;  
  418. }  
  419.   
  420.   
  421. static void s3c_led_exit(void)  
  422. {  
  423.     dbg_print("%s():%d remove LED platform drvier\n", __FUNCTION__,__LINE__);  
  424.     platform_driver_unregister(&s3c_led_driver);  
  425.     dbg_print("%s():%d remove LED platform device\n", __FUNCTION__,__LINE__);  
  426.     platform_device_unregister(&s3c_led_device);  
  427. }  
  428.   
  429. module_init(s3c_led_init);  
  430. module_exit(s3c_led_exit);  
  431.   
  432. module_param(debug, int, S_IRUGO);  
  433. module_param(dev_major, int, S_IRUGO);  
  434. module_param(dev_minor, int, S_IRUGO);  
  435.   
  436. MODULE_AUTHOR(DRV_AUTHOR);  
  437. MODULE_DESCRIPTION(DRV_DESC);  
  438. MODULE_LICENSE("GPL");  
  439. MODULE_ALIAS("platform:S3C24XX_led");</pre>  



0 0
原创粉丝点击