改进的平台设备驱动——dev和drv完全分离
这是平台设备:
1 #include <linux/fs.h> 2 #include <linux/init.h> 3 #include <linux/delay.h> 4 #include <linux/irq.h> 5 #include <asm/irq.h> 6 #include <asm/io.h> 7 #include <linux/cdev.h> 8 #include <linux/device.h> 9 #include <linux/interrupt.h> 10 #include <linux/input.h> 11 #include <linux/bitmap.h> 12 #include <asm/gpio.h> 13 #include <linux/platform_device.h> 14 15 static struct resource led_data[] = { 16 [0] = { 17 .start = 0x56000050, 18 .end = 0x56000050 + 8 -1, 19 .flags = IORESOURCE_MEM, 20 }, 21 [1] = { 22 .start = 4, 23 .end = 6, 24 .flags = IORESOURCE_IO, 25 }, 26 [2] = { 27 .start = IRQ_EINT0, 28 .end = IRQ_EINT0, 29 .name = "IRQ_EINT0", 30 .flags = IORESOURCE_IRQ, 31 }, 32 [3] = { 33 .start = IRQ_EINT2, 34 .end = IRQ_EINT2, 35 .name = "IRQ_EINT2", 36 .flags = IORESOURCE_IRQ, 37 }, 38 [4] = { 39 .start = IRQ_EINT11, 40 .end = IRQ_EINT11, 41 .name = "IRQ_EINT11", 42 .flags = IORESOURCE_IRQ, 43 } 44 }; 45 46 static struct platform_device led_device = { 47 .name = "jz2440_led", 48 .num_resources = ARRAY_SIZE(led_data), 49 .resource = led_data, 50 }; 51 52 int led_dev_init(void) 53 { 54 platform_device_register(&led_device); 55 return 0; 56 } 57 58 void led_dev_exit(void) 59 { 60 platform_device_unregister(&led_device); 61 } 62 63 module_init(led_dev_init); 64 module_exit(led_dev_exit); 65 66 MODULE_LICENSE("GPL");
这是平台驱动:
1 #include <linux/module.h> 2 #include <linux/kernel.h> 3 #include <linux/fs.h> 4 #include <linux/init.h> 5 #include <linux/delay.h> 6 #include <linux/irq.h> 7 #include <asm/irq.h> 8 #include <asm/io.h> 9 #include <linux/cdev.h> 10 #include <linux/device.h> 11 #include <linux/interrupt.h> 12 #include <linux/input.h> 13 #include <linux/bitmap.h> 14 #include <asm/gpio.h> 15 #include <linux/platform_device.h> 16 #include <linux/slab.h> 17 #include <linux/sched.h> 18 19 static volatile unsigned long *ledcon; 20 static volatile unsigned long *leddat; 21 22 static int pin_nums; 23 static int pin_start,pin_end; 24 25 static struct resource *pRes; 26 static unsigned long *pname; 27 static struct resource *irq; 28 29 static struct class *led_class; 30 static struct timer_list led_timer; 31 32 static int led_open(struct inode *inode, struct file *file) 33 { 34 int i; 35 for(i = 0; i < pin_nums; i++){ 36 *ledcon &= ~(3 << (pin_start + i) * 2); 37 *leddat &= ~(1 << (pin_start + i)); 38 *ledcon |= (1 << (pin_start + i) * 2); 39 } 40 41 return 0; 42 } 43 44 static struct file_operations led_fops = { 45 .owner = THIS_MODULE, 46 .open = led_open, 47 48 }; 49 50 static irqreturn_t led_irq(int dat, void *pvoid) 51 { 52 pRes = (struct resource *)pvoid; 53 mod_timer(&led_timer, jiffies + HZ/100); 54 55 return IRQ_HANDLED; 56 } 57 58 static int STRCMP(const char *str1,const char *str2) 59 { 60 while((*str1++) == (*str2++)){ 61 if(*str1 == '\0' && *str2 == '\0') 62 return 0; 63 else if(*str1 == '\0' || *str2 == '\0') 64 break; 65 } 66 return -1; 67 } 68 69 static int GetPinNum(struct resource *pres) 70 { 71 int i; 72 for(i = 0; i < pin_nums; i++){ 73 if(0 == STRCMP(pres->name,(char *)*(pname + i))){ 74 return i; 75 } 76 } 77 return -1; 78 } 79 80 static void led_time_function(unsigned long dat) 81 { 82 83 int ls = GetPinNum(pRes); 84 if(ls >= 0) 85 *leddat ^= (1 << (pin_start + ls)); 86 } 87 88 89 static int major; 90 static int led_probe(struct platform_device *led_dev) 91 { 92 int i; 93 struct resource *reg; 94 struct resource *led_pins; 95 96 major = register_chrdev(0,"led",&led_fops); 97 led_class = class_create(THIS_MODULE, "led"); 98 device_create(led_class,NULL,MKDEV(major,0),NULL,"led0"); 99 reg = platform_get_resource(led_dev,IORESOURCE_MEM,0); 100 led_pins = platform_get_resource(led_dev,IORESOURCE_IO,0); 101 ledcon = ioremap(reg->start,reg->end - reg->start + 1); 102 leddat = ledcon + 1; 103 pin_start = led_pins->start; 104 pin_end = led_pins->end; 105 pin_nums = led_pins->end - led_pins->start + 1; 106 pname = (unsigned long *)kmalloc(pin_nums * sizeof(unsigned long), GFP_KERNEL); //pin_nums个指针 107 for(i = 0; i < pin_nums; i++){ 108 irq = platform_get_resource(led_dev,IORESOURCE_IRQ,i); 109 request_irq(irq->start, led_irq, IRQ_TYPE_EDGE_BOTH, irq->name, irq); 110 *(pname + i)= (unsigned long)irq->name; 111 } 112 113 init_timer(&led_timer); 114 led_timer.function = led_time_function; 115 add_timer(&led_timer); 116 117 return 0; 118 } 119 120 static int led_remove(struct platform_device *led_dev) 121 { 122 int i; 123 del_timer(&led_timer); 124 for(i = 0; i < pin_nums; i++){ 125 irq = platform_get_resource(led_dev,IORESOURCE_IRQ,i); 126 free_irq(irq->start,irq); 127 } 128 kfree(pname); 129 iounmap(ledcon); 130 device_destroy(led_class, MKDEV(major,0)); 131 class_destroy(led_class); 132 unregister_chrdev(major, "led"); 133 134 return 0; 135 } 136 137 static struct platform_driver led_drv = { 138 .driver = { 139 .name = "jz2440_led", 140 .owner = THIS_MODULE, 141 }, 142 .probe = led_probe, 143 .remove = __devexit_p(led_remove), 144 }; 145 146 static int led_init(void) 147 { 148 platform_driver_register(&led_drv); 149 return 0; 150 } 151 152 static void led_exit(void) 153 { 154 platform_driver_unregister(&led_drv); 155 } 156 157 module_init(led_init); 158 module_exit(led_exit); 159 160 MODULE_LICENSE("GPL");
这是应用程序:
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <fcntl.h> 4 5 int main(int argc,char **argv) 6 { 7 int fd = open("/dev/led0",O_RDWR); 8 if(fd < 0){ 9 return -1; 10 } 11 12 while(1); 13 return 0; 14 }