系统相关
首页 > 系统相关> > Linux字符设备驱动--P1

Linux字符设备驱动--P1

作者:互联网

源码:
  1 /*****************************************************************************
  2 简    述:简单字符型驱动程序,手动静态分配设备号,手动创建设备节点
  3 ******************************************************************************/
  4 #include <linux/module.h>
  5 #include <linux/moduleparam.h>
  6 #include <linux/cdev.h>
  7 #include <linux/fs.h>
  8 #include <linux/wait.h>
  9 #include <linux/poll.h>
 10 #include <linux/sched.h>
 11 #include <linux/irq.h>
 12 #include <asm/irq.h>
 13 #include <linux/interrupt.h>
 14 
 15 
 16 #include <mach/map.h>
 17 #include <mach/gpio.h>
 18 #include <mach/regs-gpio.h>
 19 #include <plat/gpio-cfg.h>
 20 
 21 #include <linux/slab.h>
 22 
 23 #define DEVICE_NAME        "buttons"
 24 
 25 struct button_desc {
 26     int gpio;
 27     int number;
 28     char *name;    
 29 };
 30 
 31 static struct button_desc buttons[] = {
 32     { S5PV210_GPH2(0), 0, "KEY0" },
 33     { S5PV210_GPH2(1), 1, "KEY1" },
 34     { S5PV210_GPH2(2), 2, "KEY2" },
 35     { S5PV210_GPH2(3), 3, "KEY3" },
 36     { S5PV210_GPH3(0), 4, "KEY4" },
 37     { S5PV210_GPH3(1), 5, "KEY5" },
 38     { S5PV210_GPH3(2), 6, "KEY6" },
 39     { S5PV210_GPH3(3), 7, "KEY7" },
 40 };
 41 #define OK            (0)
 42 #define ERROR         (-1)
 43 
 44 struct cdev *gDev;
 45 struct file_operations *gFile;
 46 dev_t  devNum;
 47 unsigned int subDevNum = 1;
 48 int reg_major  =  232;    
 49 int reg_minor =   0;
 50 
 51 
 52 static irqreturn_t button_interrupt(int irq, void *dev_id)
 53 {
 54     struct button_desc *bdata = (struct button_desc *)dev_id;
 55 
 56     int down;
 57     unsigned tmp;
 58 
 59     tmp = gpio_get_value(bdata->gpio);
 60 
 61     /* active low */
 62     down = !tmp;
 63     printk("KEY %d: %08x\n", bdata->number, down);
 64 
 65     return IRQ_HANDLED;
 66 }
 67 
 68 int butsOpen(struct inode *p, struct file *f)
 69 {
 70     
 71         int irq;
 72     int i;
 73     int err = 0;
 74     printk(KERN_EMERG"butsOpen\r\n");
 75     for (i = 0; i < ARRAY_SIZE(buttons); i++) {
 76         if (!buttons[i].gpio)
 77             continue;
 78 
 79         irq = gpio_to_irq(buttons[i].gpio);
 80         err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, 
 81                 buttons[i].name, (void *)&buttons[i]);
 82         if (err)
 83             break;
 84     }
 85 
 86     if (err) {
 87         i--;
 88         for (; i >= 0; i--) {
 89             if (!buttons[i].gpio)
 90                 continue;
 91 
 92             irq = gpio_to_irq(buttons[i].gpio);
 93             disable_irq(irq);
 94             free_irq(irq, (void *)&buttons[i]);
 95         }
 96 
 97         return -EBUSY;
 98     }
 99     return 0;
100 }
101 
102 
103 
104 
105 int charDrvInit(void)
106 {
107     
108     devNum = MKDEV(reg_major, reg_minor);
109 
110     printk(KERN_EMERG"devNum is %d\r\n", devNum);
111     if(OK == register_chrdev_region(devNum, subDevNum, DEVICE_NAME))
112     {
113         printk(KERN_EMERG"register_chrdev_region ok\r\n");
114     }
115     else
116     {
117         printk(KERN_EMERG"register_chrdev_region error\r\n");
118         return ERROR;
119     }
120     /*if(OK == alloc_chrdev_region(&devNum, subDevNum, subDevNum,"test"))
121     {
122         printk(KERN_EMERG"register_chrdev_region ok\r\n");
123     }
124     else
125     {
126         printk(KERN_EMERG"register_chrdev_region error\r\n");
127         return ERROR;
128     }*/
129 
130     gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
131     gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
132     
133     gFile->open = butsOpen;
134 //注册设备函数到file_operations结构体gFile
135 
136    //gDev->owner = THIS_MODULE;
137     gFile->owner = THIS_MODULE;
138     cdev_init(gDev, gFile);
139 //在cdev结构体中添加指针指向file_operations结构体gFile
140     cdev_add(gDev, devNum, 3);
141 //建立设备号与cdev结构体联系
142     printk(KERN_EMERG"button driver initial done...\r\n");
143     return 0;
144 }
145 
146 void __exit charDrvExit(void)
147 {
148     int i;
149 
150     cdev_del(gDev);
151     unregister_chrdev_region(devNum, subDevNum);
152     return;
153 }
154 module_init(charDrvInit);
155 module_exit(charDrvExit);
156 MODULE_LICENSE("GPL");
View Code
 1 int butsOpen(struct inode *p, struct file *f)
 2 {
 3     
 4         int irq;
 5     int i;
 6     int err = 0;
 7     printk(KERN_EMERG"butsOpen\r\n");
 8     for (i = 0; i < ARRAY_SIZE(buttons); i++) {
 9         if (!buttons[i].gpio)
10             continue;
11 
12         irq = gpio_to_irq(buttons[i].gpio);
13         err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, 
14                 buttons[i].name, (void *)&buttons[i]);
15         if (err)
16             break;
17     }
18 
19     if (err) {
20         i--;
21         for (; i >= 0; i--) {
22             if (!buttons[i].gpio)
23                 continue;
24 
25             irq = gpio_to_irq(buttons[i].gpio);
26             disable_irq(irq);
27             free_irq(irq, (void *)&buttons[i]);
28         }
29 
30         return -EBUSY;
31     }
32     return 0;
33 }
1 #define gpio_to_irq    __gpio_to_irq
1 int __gpio_to_irq(unsigned gpio)
2 {
3     struct gpio_chip    *chip;
4     chip = gpio_to_chip(gpio);
5     return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
6 }
1 static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
2 {
3     return gpio_desc[gpio].chip;//此处的gpio_desc[gpio].chip实际完成赋值在gpio-s5pv210.c中的s5pv210_gpiolib_init(void)函数中实现
4 }

 gpio_desc[gpio].chip实际完成赋值在gpio-s5pv210.c中的s5pv210_gpiolib_init(void)函数中的实现:

 1 static __init int s5pv210_gpiolib_init(void)
 2 {
 3     struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
 4     int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
 5     int gpioint_group = 0;
 6     int i = 0;
 7 
 8     for (i = 0; i < nr_chips; i++, chip++) {
 9         if (chip->config == NULL) {
10             chip->config = &gpio_cfg;
11             chip->group = gpioint_group++;
12         }
13         if (chip->base == NULL)
14             chip->base = S5PV210_BANK_BASE(i);
15     }
16 
17     samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
18     s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
19 
20     return 0;
21 }
  1 static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
  2     {
  3         .chip    = {
  4             .base    = S5PV210_GPA0(0),
  5             .ngpio    = S5PV210_GPIO_A0_NR,
  6             .label    = "GPA0",
  7         },
  8     }, {
  9         .chip    = {
 10             .base    = S5PV210_GPA1(0),
 11             .ngpio    = S5PV210_GPIO_A1_NR,
 12             .label    = "GPA1",
 13         },
 14     }, {
 15         .chip    = {
 16             .base    = S5PV210_GPB(0),
 17             .ngpio    = S5PV210_GPIO_B_NR,
 18             .label    = "GPB",
 19         },
 20     }, {
 21         .chip    = {
 22             .base    = S5PV210_GPC0(0),
 23             .ngpio    = S5PV210_GPIO_C0_NR,
 24             .label    = "GPC0",
 25         },
 26     }, {
 27         .chip    = {
 28             .base    = S5PV210_GPC1(0),
 29             .ngpio    = S5PV210_GPIO_C1_NR,
 30             .label    = "GPC1",
 31         },
 32     }, {
 33         .chip    = {
 34             .base    = S5PV210_GPD0(0),
 35             .ngpio    = S5PV210_GPIO_D0_NR,
 36             .label    = "GPD0",
 37         },
 38     }, {
 39         .chip    = {
 40             .base    = S5PV210_GPD1(0),
 41             .ngpio    = S5PV210_GPIO_D1_NR,
 42             .label    = "GPD1",
 43         },
 44     }, {
 45         .chip    = {
 46             .base    = S5PV210_GPE0(0),
 47             .ngpio    = S5PV210_GPIO_E0_NR,
 48             .label    = "GPE0",
 49         },
 50     }, {
 51         .chip    = {
 52             .base    = S5PV210_GPE1(0),
 53             .ngpio    = S5PV210_GPIO_E1_NR,
 54             .label    = "GPE1",
 55         },
 56     }, {
 57         .chip    = {
 58             .base    = S5PV210_GPF0(0),
 59             .ngpio    = S5PV210_GPIO_F0_NR,
 60             .label    = "GPF0",
 61         },
 62     }, {
 63         .chip    = {
 64             .base    = S5PV210_GPF1(0),
 65             .ngpio    = S5PV210_GPIO_F1_NR,
 66             .label    = "GPF1",
 67         },
 68     }, {
 69         .chip    = {
 70             .base    = S5PV210_GPF2(0),
 71             .ngpio    = S5PV210_GPIO_F2_NR,
 72             .label    = "GPF2",
 73         },
 74     }, {
 75         .chip    = {
 76             .base    = S5PV210_GPF3(0),
 77             .ngpio    = S5PV210_GPIO_F3_NR,
 78             .label    = "GPF3",
 79         },
 80     }, {
 81         .chip    = {
 82             .base    = S5PV210_GPG0(0),
 83             .ngpio    = S5PV210_GPIO_G0_NR,
 84             .label    = "GPG0",
 85         },
 86     }, {
 87         .chip    = {
 88             .base    = S5PV210_GPG1(0),
 89             .ngpio    = S5PV210_GPIO_G1_NR,
 90             .label    = "GPG1",
 91         },
 92     }, {
 93         .chip    = {
 94             .base    = S5PV210_GPG2(0),
 95             .ngpio    = S5PV210_GPIO_G2_NR,
 96             .label    = "GPG2",
 97         },
 98     }, {
 99         .chip    = {
100             .base    = S5PV210_GPG3(0),
101             .ngpio    = S5PV210_GPIO_G3_NR,
102             .label    = "GPG3",
103         },
104     }, {
105         .config    = &gpio_cfg_noint,
106         .chip    = {
107             .base    = S5PV210_GPI(0),
108             .ngpio    = S5PV210_GPIO_I_NR,
109             .label    = "GPI",
110         },
111     }, {
112         .chip    = {
113             .base    = S5PV210_GPJ0(0),
114             .ngpio    = S5PV210_GPIO_J0_NR,
115             .label    = "GPJ0",
116         },
117     }, {
118         .chip    = {
119             .base    = S5PV210_GPJ1(0),
120             .ngpio    = S5PV210_GPIO_J1_NR,
121             .label    = "GPJ1",
122         },
123     }, {
124         .chip    = {
125             .base    = S5PV210_GPJ2(0),
126             .ngpio    = S5PV210_GPIO_J2_NR,
127             .label    = "GPJ2",
128         },
129     }, {
130         .chip    = {
131             .base    = S5PV210_GPJ3(0),
132             .ngpio    = S5PV210_GPIO_J3_NR,
133             .label    = "GPJ3",
134         },
135     }, {
136         .chip    = {
137             .base    = S5PV210_GPJ4(0),
138             .ngpio    = S5PV210_GPIO_J4_NR,
139             .label    = "GPJ4",
140         },
141     }, {
142         .config    = &gpio_cfg_noint,
143         .chip    = {
144             .base    = S5PV210_MP01(0),
145             .ngpio    = S5PV210_GPIO_MP01_NR,
146             .label    = "MP01",
147         },
148     }, {
149         .config    = &gpio_cfg_noint,
150         .chip    = {
151             .base    = S5PV210_MP02(0),
152             .ngpio    = S5PV210_GPIO_MP02_NR,
153             .label    = "MP02",
154         },
155     }, {
156         .config    = &gpio_cfg_noint,
157         .chip    = {
158             .base    = S5PV210_MP03(0),
159             .ngpio    = S5PV210_GPIO_MP03_NR,
160             .label    = "MP03",
161         },
162     }, {
163         .config    = &gpio_cfg_noint,
164         .chip    = {
165             .base    = S5PV210_MP04(0),
166             .ngpio    = S5PV210_GPIO_MP04_NR,
167             .label    = "MP04",
168         },
169     }, {
170         .config    = &gpio_cfg_noint,
171         .chip    = {
172             .base    = S5PV210_MP05(0),
173             .ngpio    = S5PV210_GPIO_MP05_NR,
174             .label    = "MP05",
175         },
176     }, {
177         .base    = (S5P_VA_GPIO + 0xC00),
178         .config    = &gpio_cfg_noint,
179         .irq_base = IRQ_EINT(0),
180         .chip    = {
181             .base    = S5PV210_GPH0(0),
182             .ngpio    = S5PV210_GPIO_H0_NR,
183             .label    = "GPH0",
184             .to_irq = samsung_gpiolib_to_irq,
185         },
186     }, {
187         .base    = (S5P_VA_GPIO + 0xC20),
188         .config    = &gpio_cfg_noint,
189         .irq_base = IRQ_EINT(8),
190         .chip    = {
191             .base    = S5PV210_GPH1(0),
192             .ngpio    = S5PV210_GPIO_H1_NR,
193             .label    = "GPH1",
194             .to_irq = samsung_gpiolib_to_irq,
195         },
196     }, {
197         .base    = (S5P_VA_GPIO + 0xC40),
198         .config    = &gpio_cfg_noint,
199         .irq_base = IRQ_EINT(16),
200         .chip    = {
201             .base    = S5PV210_GPH2(0),
202             .ngpio    = S5PV210_GPIO_H2_NR,
203             .label    = "GPH2",
204             .to_irq = samsung_gpiolib_to_irq,
205         },
206     }, {
207         .base    = (S5P_VA_GPIO + 0xC60),
208         .config    = &gpio_cfg_noint,
209         .irq_base = IRQ_EINT(24),
210         .chip    = {
211             .base    = S5PV210_GPH3(0),
212             .ngpio    = S5PV210_GPIO_H3_NR,
213             .label    = "GPH3",
214             .to_irq = samsung_gpiolib_to_irq,
215         },
216     },
217 };
struct s3c_gpio_chip s5pv210_gpio_4bit[]

 

1 void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
2                        int nr_chips)
3 {
4     for (; nr_chips > 0; nr_chips--, chip++) {
5         samsung_gpiolib_add_4bit(chip);
6         s3c_gpiolib_add(chip);
7     }
8 }
 1 __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
 2 {
 3     struct gpio_chip *gc = &chip->chip;//将struct s3c_gpio_chip结构体成员结构体chip赋值给struct gpio_chip结构体局部变量gc 
 4     int ret;
 5 
 6     BUG_ON(!chip->base);
 7     BUG_ON(!gc->label);
 8     BUG_ON(!gc->ngpio);
 9 
10     spin_lock_init(&chip->lock);
11 
12     if (!gc->direction_input)
13         gc->direction_input = s3c_gpiolib_input;
14     if (!gc->direction_output)
15         gc->direction_output = s3c_gpiolib_output;
16     if (!gc->set)
17         gc->set = s3c_gpiolib_set;
18     if (!gc->get)
19         gc->get = s3c_gpiolib_get;
20 
21 #ifdef CONFIG_PM
22     if (chip->pm != NULL) {
23         if (!chip->pm->save || !chip->pm->resume)
24             printk(KERN_ERR "gpio: %s has missing PM functions\n",
25                    gc->label);
26     } else
27         printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
28 #endif
29 
30     /* gpiochip_add() prints own failure message on error. */
31     ret = gpiochip_add(gc);
32     if (ret >= 0)
33         s3c_gpiolib_track(chip);
34 }
 1 int gpiochip_add(struct gpio_chip *chip)
 2 {
 3     unsigned long    flags;
 4     int        status = 0;
 5     unsigned    id;
 6     int        base = chip->base;
 7 
 8     if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))
 9             && base >= 0) {
10         status = -EINVAL;
11         goto fail;
12     }
13 
14     spin_lock_irqsave(&gpio_lock, flags);
15 
16     if (base < 0) {
17         base = gpiochip_find_base(chip->ngpio);
18         if (base < 0) {
19             status = base;
20             goto unlock;
21         }
22         chip->base = base;
23     }
24 
25     /* these GPIO numbers must not be managed by another gpio_chip */
26     for (id = base; id < base + chip->ngpio; id++) {
27         if (gpio_desc[id].chip != NULL) {
28             status = -EBUSY;
29             break;
30         }
31     }
32     if (status == 0) {
33         for (id = base; id < base + chip->ngpio; id++) {
34             gpio_desc[id].chip = chip;//在这里gpio_desc[id].chip和struct s3c_gpio_chip建立联系
35 
36             /* REVISIT:  most hardware initializes GPIOs as
37              * inputs (often with pullups enabled) so power
38              * usage is minimized.  Linux code should set the
39              * gpio direction first thing; but until it does,
40              * we may expose the wrong direction in sysfs.
41              */
42             gpio_desc[id].flags = !chip->direction_input
43                 ? (1 << FLAG_IS_OUT)
44                 : 0;
45         }
46     }
47 
48     of_gpiochip_add(chip);
49 
50 unlock:
51     spin_unlock_irqrestore(&gpio_lock, flags);
52 
53     if (status)
54         goto fail;
55 
56     status = gpiochip_export(chip);
57     if (status)
58         goto fail;
59 
60     return 0;
61 fail:
62     /* failures here can mean systems won't boot... */
63     pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n",
64         chip->base, chip->base + chip->ngpio - 1,
65         chip->label ? : "generic");
66     return status;
67 }

 

 

标签:字符,P1,S5PV210,irq,chip,ngpio,base,Linux,gpio
来源: https://www.cnblogs.com/embeded-linux/p/10690648.html