| 
 
| | 【飞凌】platform_device + miscdevice 模式的LED驱动程序 |  | 本文转引自 飞凌嵌入式 Linux技术交流区 www.witech.com.cn 感谢作者朋友的分享精神!
 这是我最近学习Linux驱动模型的成果,发出来大家共同学习一下,该程序还有很多缺陷,希望高手能不吝赐教
 #include <linux/types.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include<linux/init.h>
 #include<linux/module.h>
 #include<asm/io.h>
 #include<linux/miscdevice.h>
 #include<linux/ioctl.h>
 #include<linux/device.h>
 #include<linux/platform_device.h>
 MODULE_AUTHOR("YUZIQIANG");
 MODULE_DESCRIPTION("LEDS DRIVE");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
 #define DEV_NAME        "FL2440LED"
 #define LED_MAGIC        'L'
 #define LED_ON                _IOW(LED_MAGIC,0,int)
 #define LED_OFF                _IOW(LED_MAGIC,1,int)
 #define LED_MINOR        125
 #define LED_MAJOR        10
 #define LED_CON                0
 #define LED_DAT                4
 #define LED_UP                8
 
 int major;
 dev_t devNu;
 struct cdev ledCdev ;
 void   *ledbase;
 
 ssize_t  led_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset);
 ssize_t  led_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset);
 int led_open(struct inode *inode,struct file *filp);
 int led_release(struct inode *inode,struct file *filp);
 int led_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg);
 static int led_probe(struct platform_device *pdev);
 static int led_remove(struct platform_device *pdev);
 
 struct resource        s3c_led_resource[]        ={
 [0]={
 .start        =        0x56000010,
 .end                =        0x5600001b,
 .flags        =        IORESOURCE_MEM,
 }
 };
 
 
 struct file_operations led_opt ={
 .owner                =        THIS_MODULE,
 .ioctl                =        led_ioctl,
 .open                =        led_open,
 .read                =        led_read,
 .write                =        led_write,
 .release        =        led_release,
 };
 static struct miscdevice misc_led ={
 .minor        =        LED_MINOR,
 .name        =        "led",
 .fops        =        &led_opt,
 };
 struct platform_device  ledDevice= {
 .name        =        "led",
 .id                =        -1,//why
 .num_resources        =        ARRAY_SIZE(s3c_led_resource),
 .resource        =        s3c_led_resource,
 .dev                        =        {
 .release        =        led_release,
 }
 };
 
 struct platform_driver         ledDriver ={
 .probe        =        led_probe,
 .remove        =        led_remove,
 .driver        =        {
 .owner        =        THIS_MODULE,
 .name        =        "led",
 }
 };
 
 
 int led_open(struct inode *inode,struct file *filp)
 {
 
 //GPBCON        =        0x55555555;
 writel(0x55555555,ledbase+LED_CON);
 //GPBUP        =        0xffffffff;
 writel(0,ledbase+LED_UP);
 writel(0,ledbase+LED_DAT);
 //GPBDAT        =        0x00000000;
 printk("\nopen success \n");
 return 0;
 }
 ssize_t  led_read(struct file *filp,char __user *buffer,size_t size,loff_t *offset)
 {
 return 0;
 }
 ssize_t  led_write(struct file *filp,const char __user *buffer,size_t size,loff_t *offset)
 {
 return 0;
 }
 int led_release(struct inode *inode,struct file *filp)
 {
 return 0;
 }
 int led_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
 {
 unsigned long tmp;
 int pin=0;
 ///check the command is in the right form
 if(arg>4||arg<1)
 return -1;
 if(_IOC_NR(cmd)>1||_IOC_NR(cmd)<0)
 return -1;
 if(arg==1)
 pin=5;
 else if(arg==2)
 pin = 6;
 else if(arg==3)
 pin=8;
 else if(arg==4)
 pin=10;
 else pin= 0;
 do {
 if(cmd==LED_ON)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp &=(~(1<<pin));
 writel(tmp,ledbase +LED_DAT);
 }
 else if(cmd==LED_OFF)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp |=(1<<pin);
 writel(tmp,ledbase +LED_DAT);
 }
 else
 printk("command error");
 break;
 }
 while(0);
 ///command switch
 /*
 switch (arg) {
 case 1:
 if(cmd==LED_ON)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp &=(~(1<<5));
 writel(tmp,ledbase +LED_DAT);
 }
 else if(cmd==LED_OFF)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp |=(1<<5);
 writel(tmp,ledbase +LED_DAT);
 }
 else
 printk("command error");
 break;
 case 2:
 if(cmd==LED_ON)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp &=(~(1<<6));
 writel(tmp,ledbase +LED_DAT);
 }
 else if(cmd==LED_OFF)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp |=(1<<6);
 writel(tmp,ledbase +LED_DAT);
 }
 else
 printk("command error");
 break;
 case 3:
 if(cmd==LED_ON)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp &=(~(1<<8));
 writel(tmp,ledbase +LED_DAT);
 }
 else if(cmd==LED_OFF)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp |=(1<<8);
 writel(tmp,ledbase +LED_DAT);
 }
 else
 printk("command error");
 break;
 case 4:
 if(cmd==LED_ON)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp &=(~(1<<10));
 writel(tmp,ledbase +LED_DAT);
 }
 else if(cmd==LED_OFF)
 {
 tmp        =        readl(ledbase+LED_DAT);
 tmp |=(1<<10);
 writel(tmp,ledbase +LED_DAT);
 }
 else
 printk("command error");
 break;
 default :
 printk("error");
 break;
 }
 */
 return 0;
 }
 static int led_probe(struct platform_device *pdev)
 {
 struct resource *res;
 struct device *dev;
 int size;
 int ret;
 dev=&pdev->dev;
 printk("\nMatch success");
 res=        platform_get_resource(pdev,IORESOURCE_MEM,0);
 if(res==NULL)
 {
 dev_err(dev,"no memory resource specified\n");
 return -ENOENT;
 }
 size        =        res->end-res->start +1;
 ledbase        =        ioremap(res->start,size);
 if(ledbase==NULL)
 {
 dev_err(dev,"fail to ioremap() region\n");
 ret=-EINVAL;
 goto err_req;
 }
 ret=misc_register(&misc_led);
 if(ret)
 {
 dev_err(dev,"cannot register led  miscdev ");
 goto err_misc;
 }
 err_misc:
 iounmap(ledbase);
 err_req:
 
 return ret;
 &nb
 
 
 
 | 
 | 
 |