20150218【改进信号量】IMX257实现GPIO-IRQ中断按键获取键值驱动程序
分类:
IT文章
•
2022-05-02 18:23:43
【改进信号量】IMX257实现GPIO-IRQ中断按键获取键值驱动程序
2015-02-18 李海沿
前面我们使用POLL查询方式来实现GPIO-IRQ按键中断程序
这里我们来使用信号量,让我们的驱动同时只能有一个应用程序打开。
一、首先在前面代码的基础上来一个简单的信号
1.定义一个全局的整形变量

2.在打开函数中,每次进入打开函数canopen都自减1,

3.当我们不使用时,在realease 中canopen自加1

4.这样就实现了一个简单的信号量,我们编译,测试

当我们使用两个应用程序来同时打开设备时,看看会发生什么:

可以发现,由于我们后台已经打开一个应用程序了,所以,如果此时我们再用另外一个应用程序打开的话,则会报错,can't open
好了,到这里,我们已经基本上实现了一个简陋的信号量程序。
附上驱动代码
1 /******************************
2 linux key_query
3 *****************************/
4 #include <linux/module.h>
5 #include <linux/init.h>
6 #include <linux/kernel.h>
7 #include <linux/delay.h>
8 #include <linux/types.h>
9 #include <linux/ioctl.h>
10 #include <linux/gpio.h>
11 #include <linux/fs.h>
12 #include <linux/device.h>
13 #include <linux/uaccess.h>
14 #include <linux/irq.h>
15 #include <linux/wait.h>
16 #include <linux/sched.h>//error: 'TASK_INTERRUPTIBLE' undeclared
17 #include <linux/interrupt.h>
18 #include <linux/poll.h>
19
20 #include "mx257_gpio.h"
21 #include "mx25_pins.h"
22 #include "iomux.h"
23
24 #define Driver_NAME "key_interrupt"
25 #define DEVICE_NAME "key_interrupt"
26
27 #define GPIO2_21 MX25_PIN_CLKO
28 #define GPIO3_15 MX25_PIN_EXT_ARMCLK
29 #define GPIO2_10 MX25_PIN_A24
30 #define GPIO2_11 MX25_PIN_A25
31 #define GPIO2_8 MX25_PIN_A22
32 #define GPIO2_9 MX25_PIN_A23
33 #define GPIO2_6 MX25_PIN_A20
34 #define GPIO2_7 MX25_PIN_A21
35 //command
36 #define key_input 0
37 #define version 1
38 //定义各个按键按下的键值
39 struct pin_desc{
40 unsigned int pin;
41 unsigned int key_val;
42 };
43 //当按键按下时,键值分别为 以下值
44 struct pin_desc pins_desc[8] = {
45 {GPIO2_6, 0x01},
46 {GPIO2_7, 0x02},
47 {GPIO2_8, 0x03},
48 {GPIO2_9, 0x04},
49 {GPIO2_10, 0x05},
50 {GPIO2_11, 0x06},
51 {GPIO2_21, 0x07},
52 {GPIO3_15, 0x08},
53 };
54 //定义一个全局变量,用于保存按下的键值
55 static unsigned int key_val;
56
57 //信号量定义
58 static int canopen = 1;
59
60 //interrupt head
61 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);
62 static volatile unsigned char ev_press;
63
64 static int major=0;
65
66 //auto to create device node
67 static struct class *drv_class = NULL;
68 static struct class_device *drv_class_dev = NULL;
69
70
71 /* 应用程序对设备文件/dev/key_query执行open(...)时,
72 * 就会调用key_open函数*/
73 static int key_open(struct inode *inode, struct file *file)
74 {
75 printk("<0>function open!
");
76 if(--canopen != 0)
77 {
78 canopen ++;
79 return -EBUSY;
80 }
81
82 return 0;
83 }
84
85 /* 中断程序key_irq */
86 static irqreturn_t key_irq(int irq, void *dev_id)
87 {
88 struct pin_desc * pindesc = (struct pin_desc *)dev_id;
89 //发生了中断
90 //printk("<0>function interrupt key_irq!
");
91 //获取按键键值
92 if(gpio_get_value(IOMUX_TO_GPIO(pindesc->pin))){
93 /* 按下 */
94 key_val = pindesc->key_val;
95 }else{
96 key_val = 0x80 | pindesc->key_val;
97 }
98 printk("<0>get key 0x%x",key_val);
99 ev_press = 1;
100 wake_up_interruptible(&key_interrupt_wait);
101
102 return IRQ_RETVAL(IRQ_HANDLED);
103 }
104
105
106 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
107 {
108 int ret;
109 //如果按键没有按下,没有中断,休眠
110 //wait_event_interruptible(key_interrupt_wait,ev_press);
111
112 ret = copy_to_user(buff,&key_val,sizeof(key_val));
113 if(ret){
114 ;
115 }
116 ev_press = 0;
117 return sizeof(key_val);
118
119 //int cnt=0;
120 //unsigned char key_vals[8];
121
122 /*
123 // reading the pins value
124 key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
125 key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
126 key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
127 key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
128 key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
129 key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
130 key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
131 key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
132
133 //printk("<0>%04d key pressed: %d %d %d %d %d %d %d %d
",cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]);
134 */
135 }
136
137 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
138 {
139 printk("<0>function write!
");
140
141 return 1;
142 }
143
144 static int key_release(struct inode *inode, struct file *filp)
145 {
146 canopen ++;
147 printk("<0>function release!
");
148 //释放中断
149 free_irq(IOMUX_TO_IRQ(GPIO2_21), &pins_desc[6]);
150 //free_irq(IOMUX_TO_IRQ(GPIO3_15),&pins_desc[7]);
151 free_irq(IOMUX_TO_IRQ(GPIO2_11), &pins_desc[5]);
152 free_irq(IOMUX_TO_IRQ(GPIO2_10), &pins_desc[4]);
153 free_irq(IOMUX_TO_IRQ(GPIO2_9), &pins_desc[3]);
154 //free_irq(IOMUX_TO_IRQ(GPIO2_8), &pins_desc[2]);
155 free_irq(IOMUX_TO_IRQ(GPIO2_7), &pins_desc[1]);
156 free_irq(IOMUX_TO_IRQ(GPIO2_6), &pins_desc[0]);
157 return 0;
158 }
159
160 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
161 {
162 int ret;
163 printk("<0>function ioctl!
");
164 switch (command) {
165 case key_input:
166 //设置所有的引脚为输入
167 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
168 gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
169 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
170 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
171 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
172 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
173 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
174 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
175 printk("<0>have setting all pins to gpio input mod !
");
176 //设置GPIO引脚为上拉模式
177 mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
178 mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
179 //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
180 mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
181 mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
182 mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
183 mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
184 //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
185
186 //设置GPIO引脚中断 ,下降沿触发
187 request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_6", &pins_desc[0]);
188 request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_7", &pins_desc[1]);
189 request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_9", &pins_desc[3]);
190 request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_10", &pins_desc[4]);
191 request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_11", &pins_desc[5]);
192 request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_21", &pins_desc[6]);
193 //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO3_15", &pins_desc[7]);
194 //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_8", &pins_desc[2]);
195 printk("<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !
");
196
197 break;
198 case version:
199 printk("<0>hello,the version is 0.1.0
");
200 break;
201 default:
202 printk("<0>command error
");
203 printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;
");
204 printk("<0>command: <key_input> <version>
");
205 return -1;
206 }
207 return 0;
208 }
209 static unsigned key_poll(struct file *file,poll_table *wait)
210 {
211 unsigned int mask = 0;
212 //程序不立即睡眠,而是继续等待
213 poll_wait(file,&key_interrupt_wait,wait);
214 //如果按键按下
215 if(ev_press)
216 mask |= POLLIN | POLLRDNORM;
217
218 return mask;
219 }
220
221 /* 这个结构是字符设备驱动程序的核心
222 * 当应用程序操作设备文件时所调用的open、read、write等函数,
223 * 最终会调用这个结构中指定的对应函数
224 */
225 static struct file_operations key_fops = {
226 .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
227 .open = key_open,
228 .read = key_read,
229 .write = key_write,
230 .release= key_release,
231 .ioctl = key_ioctl,
232 .poll = key_poll,
233 };
234
235 /*
236 * 执行insmod命令时就会调用这个函数
237 */
238 static int __init key_irq_init(void)
239 {
240 printk("<0>
Hello,this is %s module!
",Driver_NAME);
241 //register and mknod
242 major = register_chrdev(0,Driver_NAME,&key_fops);
243 drv_class = class_create(THIS_MODULE,Driver_NAME);
244 drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME); /*/dev/key_query*/
245
246 //set all pins to GPIO mod ALF5
247 mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
248 mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
249 mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
250 mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
251 mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
252 mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
253 mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
254 mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
255 //request IOMUX GPIO
256 gpio_request(IOMUX_TO_GPIO(GPIO2_21), "GPIO2_21");
257 gpio_request(IOMUX_TO_GPIO(GPIO3_15), "GPIO3_15");
258 gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");
259 gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");
260 gpio_request(IOMUX_TO_GPIO(GPIO2_8), "GPIO2_8");
261 gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");
262 gpio_request(IOMUX_TO_GPIO(GPIO2_6), "GPIO2_6");
263 gpio_request(IOMUX_TO_GPIO(GPIO2_7), "GPIO2_7");
264
265
266 return 0;
267 }
268
269 /*
270 * 执行rmmod命令时就会调用这个函数
271 */
272 static void __exit key_irq_exit(void)
273 {
274 printk("<0>
Goodbye,%s!
",Driver_NAME);
275
276 unregister_chrdev(major,Driver_NAME);
277 device_unregister(drv_class_dev);
278 class_destroy(drv_class);
279
280 /* free gpios */
281 mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);
282 mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);
283 mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
284 mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
285 mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);
286 mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
287 mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);
288 mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);
289
290 gpio_free(IOMUX_TO_GPIO(GPIO2_21));
291 gpio_free(IOMUX_TO_GPIO(GPIO3_15));
292 gpio_free(IOMUX_TO_GPIO(GPIO2_10));
293 gpio_free(IOMUX_TO_GPIO(GPIO2_11));
294 gpio_free(IOMUX_TO_GPIO(GPIO2_8));
295 gpio_free(IOMUX_TO_GPIO(GPIO2_9));
296 gpio_free(IOMUX_TO_GPIO(GPIO2_6));
297 gpio_free(IOMUX_TO_GPIO(GPIO2_7));
298
299 }
300
301 /* 这两行指定驱动程序的初始化函数和卸载函数 */
302 module_init(key_irq_init);
303 module_exit(key_irq_exit);
304
305 /* 描述驱动程序的一些信息,不是必须的 */
306 MODULE_AUTHOR("Lover雪");
307 MODULE_VERSION("0.1.0");
308 MODULE_DESCRIPTION("IMX257 key Driver");
309 MODULE_LICENSE("GPL");
View Code
附上应用程序代码:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <termios.h>
8 #include <errno.h>
9 #include <limits.h>
10 #include <asm/ioctls.h>
11 #include <time.h>
12 #include <pthread.h>
13 #include <poll.h>
14
15 #include "mx257_gpio.h"
16
17 #define key_input 0
18 #define version 1
19
20
21 int main(int argc, char **argv)
22 {
23 int fd;
24 int i=0,cnt=0;
25 unsigned char key_val[1];
26 struct pollfd fds[1];
27 int ret;
28 fd = open("/dev/key_interrupt",O_RDWR );
29 if(fd < 0){
30 printf("can't open !!!
");
31 }
32 ioctl(fd,version,NULL);
33 ioctl(fd,key_input,NULL);
34
35 fds[0].fd = fd;
36 fds[0].events = POLLIN;
37 while(1){
38 ret = poll(fds,1,5000);
39 if(ret == 0)
40 printf("time out
");
41 else{
42 read(fd,key_val,1);
43 printf("%04d key pressed: 0x%x
",cnt++,key_val[0]);
44 }
45 }
46 return 0;
47 }
View Code
二、改进 原子操作
由于前面的代码中信号量自减和检测信号量不是同时进行的,可能被打断,虽然概率很小,但是,也是有可能会发生。
为了避免这个问题,这里我们使用原子操作来实现信号量的改变。
所谓原子操作,就是不可被打断,从而保证了前面我们所说到的问题。
具体方法如下。
atomic_t v = ATOMIC_INIT(0); //定义原子信号v,并且赋初值为0
atomic_read(atomic_t *v); //返回原子变量的值
void atomic_inc(atomic_t *v); //原子变量增加1
void atomic_dec(atomic_t *v); //原子变量减少1
int atomic_dec_and_test(atomic_t *v);
//自减操作后测试是否为0,为0则返回true,否则返回false
驱动程序中修改如下:
1. 定义原子信号canopen,并且赋初值1

2.在open函数中检测信号量是否为1,否则就无法打开。

3.在释放函数中信号量值加1

4.编译和测试,可以发现结果和上面的代码一样

附上驱动程序源程序:
1 /******************************
2 linux key_query
3 *****************************/
4 #include <linux/module.h>
5 #include <linux/init.h>
6 #include <linux/kernel.h>
7 #include <linux/delay.h>
8 #include <linux/types.h>
9 #include <linux/ioctl.h>
10 #include <linux/gpio.h>
11 #include <linux/fs.h>
12 #include <linux/device.h>
13 #include <linux/uaccess.h>
14 #include <linux/irq.h>
15 #include <linux/wait.h>
16 #include <linux/sched.h>//error: 'TASK_INTERRUPTIBLE' undeclared
17 #include <linux/interrupt.h>
18 #include <linux/poll.h>
19
20 #include "mx257_gpio.h"
21 #include "mx25_pins.h"
22 #include "iomux.h"
23
24 #define Driver_NAME "key_interrupt"
25 #define DEVICE_NAME "key_interrupt"
26
27 #define GPIO2_21 MX25_PIN_CLKO
28 #define GPIO3_15 MX25_PIN_EXT_ARMCLK
29 #define GPIO2_10 MX25_PIN_A24
30 #define GPIO2_11 MX25_PIN_A25
31 #define GPIO2_8 MX25_PIN_A22
32 #define GPIO2_9 MX25_PIN_A23
33 #define GPIO2_6 MX25_PIN_A20
34 #define GPIO2_7 MX25_PIN_A21
35 //command
36 #define key_input 0
37 #define version 1
38 //定义各个按键按下的键值
39 struct pin_desc{
40 unsigned int pin;
41 unsigned int key_val;
42 };
43 //当按键按下时,键值分别为 以下值
44 struct pin_desc pins_desc[8] = {
45 {GPIO2_6, 0x01},
46 {GPIO2_7, 0x02},
47 {GPIO2_8, 0x03},
48 {GPIO2_9, 0x04},
49 {GPIO2_10, 0x05},
50 {GPIO2_11, 0x06},
51 {GPIO2_21, 0x07},
52 {GPIO3_15, 0x08},
53 };
54 //定义一个全局变量,用于保存按下的键值
55 static unsigned int key_val;
56
57 //信号量定义
58 //static int canopen = 1;
59 //定义原子信号量
60 static atomic_t canopen = ATOMIC_INIT(1); //定义原子信号canopen,并且赋初值1
61
62 //interrupt head
63 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);
64 static volatile unsigned char ev_press;
65
66 static int major=0;
67
68 //auto to create device node
69 static struct class *drv_class = NULL;
70 static struct class_device *drv_class_dev = NULL;
71
72
73 /* 应用程序对设备文件/dev/key_query执行open(...)时,
74 * 就会调用key_open函数*/
75 static int key_open(struct inode *inode, struct file *file)
76 {
77 printk("<0>function open!
");
78 //if(--canopen != 0)
79 if(!atomic_dec_and_test(&canopen))
80 {
81 //canopen ++;
82 atomic_inc(&canopen);
83 return -EBUSY;
84 }
85
86 return 0;
87 }
88
89 /* 中断程序key_irq */
90 static irqreturn_t key_irq(int irq, void *dev_id)
91 {
92 struct pin_desc * pindesc = (struct pin_desc *)dev_id;
93 //发生了中断
94 //printk("<0>function interrupt key_irq!
");
95 //获取按键键值
96 if(gpio_get_value(IOMUX_TO_GPIO(pindesc->pin))){
97 /* 按下 */
98 key_val = pindesc->key_val;
99 }else{
100 key_val = 0x80 | pindesc->key_val;
101 }
102 printk("<0>get key 0x%x",key_val);
103 ev_press = 1;
104 wake_up_interruptible(&key_interrupt_wait);
105
106 return IRQ_RETVAL(IRQ_HANDLED);
107 }
108
109
110 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
111 {
112 int ret;
113 //如果按键没有按下,没有中断,休眠
114 //wait_event_interruptible(key_interrupt_wait,ev_press);
115
116 ret = copy_to_user(buff,&key_val,sizeof(key_val));
117 if(ret){
118 ;
119 }
120 ev_press = 0;
121 return sizeof(key_val);
122
123 //int cnt=0;
124 //unsigned char key_vals[8];
125
126 /*
127 // reading the pins value
128 key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
129 key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
130 key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
131 key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
132 key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
133 key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
134 key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
135 key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
136
137 //printk("<0>%04d key pressed: %d %d %d %d %d %d %d %d
",cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]);
138 */
139 }
140
141 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
142 {
143 printk("<0>function write!
");
144
145 return 1;
146 }
147
148 static int key_release(struct inode *inode, struct file *filp)
149 {
150 //canopen ++;
151 atomic_inc(&canopen);
152 printk("<0>function release!
");
153 //释放中断
154 free_irq(IOMUX_TO_IRQ(GPIO2_21), &pins_desc[6]);
155 //free_irq(IOMUX_TO_IRQ(GPIO3_15),&pins_desc[7]);
156 free_irq(IOMUX_TO_IRQ(GPIO2_11), &pins_desc[5]);
157 free_irq(IOMUX_TO_IRQ(GPIO2_10), &pins_desc[4]);
158 free_irq(IOMUX_TO_IRQ(GPIO2_9), &pins_desc[3]);
159 //free_irq(IOMUX_TO_IRQ(GPIO2_8), &pins_desc[2]);
160 free_irq(IOMUX_TO_IRQ(GPIO2_7), &pins_desc[1]);
161 free_irq(IOMUX_TO_IRQ(GPIO2_6), &pins_desc[0]);
162 return 0;
163 }
164
165 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
166 {
167 int ret;
168 printk("<0>function ioctl!
");
169 switch (command) {
170 case key_input:
171 //设置所有的引脚为输入
172 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
173 gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
174 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
175 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
176 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
177 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
178 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
179 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
180 printk("<0>have setting all pins to gpio input mod !
");
181 //设置GPIO引脚为上拉模式
182 mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
183 mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
184 //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
185 mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
186 mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
187 mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
188 mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
189 //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
190
191 //设置GPIO引脚中断 ,下降沿触发
192 request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_6", &pins_desc[0]);
193 request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_7", &pins_desc[1]);
194 request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_9", &pins_desc[3]);
195 request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_10", &pins_desc[4]);
196 request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_11", &pins_desc[5]);
197 request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_21", &pins_desc[6]);
198 //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO3_15", &pins_desc[7]);
199 //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_8", &pins_desc[2]);
200 printk("<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !
");
201
202 break;
203 case version:
204 printk("<0>hello,the version is 0.1.0
");
205 break;
206 default:
207 printk("<0>command error
");
208 printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;
");
209 printk("<0>command: <key_input> <version>
");
210 return -1;
211 }
212 return 0;
213 }
214 static unsigned key_poll(struct file *file,poll_table *wait)
215 {
216 unsigned int mask = 0;
217 //程序不立即睡眠,而是继续等待
218 poll_wait(file,&key_interrupt_wait,wait);
219 //如果按键按下
220 if(ev_press)
221 mask |= POLLIN | POLLRDNORM;
222
223 return mask;
224 }
225
226 /* 这个结构是字符设备驱动程序的核心
227 * 当应用程序操作设备文件时所调用的open、read、write等函数,
228 * 最终会调用这个结构中指定的对应函数
229 */
230 static struct file_operations key_fops = {
231 .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
232 .open = key_open,
233 .read = key_read,
234 .write = key_write,
235 .release= key_release,
236 .ioctl = key_ioctl,
237 .poll = key_poll,
238 };
239
240 /*
241 * 执行insmod命令时就会调用这个函数
242 */
243 static int __init key_irq_init(void)
244 {
245 printk("<0>
Hello,this is %s module!
",Driver_NAME);
246 //register and mknod
247 major = register_chrdev(0,Driver_NAME,&key_fops);
248 drv_class = class_create(THIS_MODULE,Driver_NAME);
249 drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME); /*/dev/key_query*/
250
251 //set all pins to GPIO mod ALF5
252 mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
253 mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
254 mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
255 mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
256 mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
257 mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
258 mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
259 mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
260 //request IOMUX GPIO
261 gpio_request(IOMUX_TO_GPIO(GPIO2_21), "GPIO2_21");
262 gpio_request(IOMUX_TO_GPIO(GPIO3_15), "GPIO3_15");
263 gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");
264 gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");
265 gpio_request(IOMUX_TO_GPIO(GPIO2_8), "GPIO2_8");
266 gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");
267 gpio_request(IOMUX_TO_GPIO(GPIO2_6), "GPIO2_6");
268 gpio_request(IOMUX_TO_GPIO(GPIO2_7), "GPIO2_7");
269
270
271 return 0;
272 }
273
274 /*
275 * 执行rmmod命令时就会调用这个函数
276 */
277 static void __exit key_irq_exit(void)
278 {
279 printk("<0>
Goodbye,%s!
",Driver_NAME);
280
281 unregister_chrdev(major,Driver_NAME);
282 device_unregister(drv_class_dev);
283 class_destroy(drv_class);
284
285 /* free gpios */
286 mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);
287 mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);
288 mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
289 mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
290 mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);
291 mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
292 mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);
293 mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);
294
295 gpio_free(IOMUX_TO_GPIO(GPIO2_21));
296 gpio_free(IOMUX_TO_GPIO(GPIO3_15));
297 gpio_free(IOMUX_TO_GPIO(GPIO2_10));
298 gpio_free(IOMUX_TO_GPIO(GPIO2_11));
299 gpio_free(IOMUX_TO_GPIO(GPIO2_8));
300 gpio_free(IOMUX_TO_GPIO(GPIO2_9));
301 gpio_free(IOMUX_TO_GPIO(GPIO2_6));
302 gpio_free(IOMUX_TO_GPIO(GPIO2_7));
303
304 }
305
306 /* 这两行指定驱动程序的初始化函数和卸载函数 */
307 module_init(key_irq_init);
308 module_exit(key_irq_exit);
309
310 /* 描述驱动程序的一些信息,不是必须的 */
311 MODULE_AUTHOR("Lover雪");
312 MODULE_VERSION("0.1.0");
313 MODULE_DESCRIPTION("IMX257 key Driver");
314 MODULE_LICENSE("GPL");
View Code
1 /******************************
2 linux key_query
3 *****************************/
4 #include <linux/module.h>
5 #include <linux/init.h>
6 #include <linux/kernel.h>
7 #include <linux/delay.h>
8 #include <linux/types.h>
9 #include <linux/ioctl.h>
10 #include <linux/gpio.h>
11 #include <linux/fs.h>
12 #include <linux/device.h>
13 #include <linux/uaccess.h>
14 #include <linux/irq.h>
15 #include <linux/wait.h>
16 #include <linux/sched.h>//error: 'TASK_INTERRUPTIBLE' undeclared
17 #include <linux/interrupt.h>
18 #include <linux/poll.h>
19
20 #include "mx257_gpio.h"
21 #include "mx25_pins.h"
22 #include "iomux.h"
23
24 #define Driver_NAME "key_interrupt"
25 #define DEVICE_NAME "key_interrupt"
26
27 #define GPIO2_21 MX25_PIN_CLKO
28 #define GPIO3_15 MX25_PIN_EXT_ARMCLK
29 #define GPIO2_10 MX25_PIN_A24
30 #define GPIO2_11 MX25_PIN_A25
31 #define GPIO2_8 MX25_PIN_A22
32 #define GPIO2_9 MX25_PIN_A23
33 #define GPIO2_6 MX25_PIN_A20
34 #define GPIO2_7 MX25_PIN_A21
35 //command
36 #define key_input 0
37 #define version 1
38 //定义各个按键按下的键值
39 struct pin_desc{
40 unsigned int pin;
41 unsigned int key_val;
42 };
43 //当按键按下时,键值分别为 以下值
44 struct pin_desc pins_desc[8] = {
45 {GPIO2_6, 0x01},
46 {GPIO2_7, 0x02},
47 {GPIO2_8, 0x03},
48 {GPIO2_9, 0x04},
49 {GPIO2_10, 0x05},
50 {GPIO2_11, 0x06},
51 {GPIO2_21, 0x07},
52 {GPIO3_15, 0x08},
53 };
54 //定义一个全局变量,用于保存按下的键值
55 static unsigned int key_val;
56
57 //信号量定义
58 //static int canopen = 1;
59 //定义原子信号量
60 //static atomic_t canopen = ATOMIC_INIT(1); //定义原子信号canopen,并且赋初值1
61 //定义信号量
62 struct semaphore canopen; //定义一个信号量
63
64 //interrupt head
65 static DECLARE_WAIT_QUEUE_HEAD(key_interrupt_wait);
66 static volatile unsigned char ev_press;
67
68 static int major=0;
69
70 //auto to create device node
71 static struct class *drv_class = NULL;
72 static struct class_device *drv_class_dev = NULL;
73
74
75 /* 应用程序对设备文件/dev/key_query执行open(...)时,
76 * 就会调用key_open函数*/
77 static int key_open(struct inode *inode, struct file *file)
78 {
79 printk("<0>function open!
");
80 down(&canopen); //申请信号量
81 //if(--canopen != 0)
82 /*if(!atomic_dec_and_test(&canopen))
83 {
84 //canopen ++;
85 atomic_inc(&canopen);
86 return -EBUSY;
87 }*/
88
89 return 0;
90 }
91
92 /* 中断程序key_irq */
93 static irqreturn_t key_irq(int irq, void *dev_id)
94 {
95 struct pin_desc * pindesc = (struct pin_desc *)dev_id;
96 //发生了中断
97 //printk("<0>function interrupt key_irq!
");
98 //获取按键键值
99 if(gpio_get_value(IOMUX_TO_GPIO(pindesc->pin))){
100 /* 按下 */
101 key_val = pindesc->key_val;
102 }else{
103 key_val = 0x80 | pindesc->key_val;
104 }
105 printk("<0>get key 0x%x",key_val);
106 ev_press = 1;
107 wake_up_interruptible(&key_interrupt_wait);
108
109 return IRQ_RETVAL(IRQ_HANDLED);
110 }
111
112
113 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
114 {
115 int ret;
116 //如果按键没有按下,没有中断,休眠
117 //wait_event_interruptible(key_interrupt_wait,ev_press);
118
119 ret = copy_to_user(buff,&key_val,sizeof(key_val));
120 if(ret){
121 ;
122 }
123 ev_press = 0;
124 return sizeof(key_val);
125
126 //int cnt=0;
127 //unsigned char key_vals[8];
128
129 /*
130 // reading the pins value
131 key_vals[0] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_6)) ? 1 : 0;
132 key_vals[1] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_7)) ? 1 : 0;
133 key_vals[2] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_8)) ? 1 : 0;
134 key_vals[3] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_9)) ? 1 : 0;
135 key_vals[4] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_10)) ? 1 : 0;
136 key_vals[5] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_11)) ? 1 : 0;
137 key_vals[6] = gpio_get_value(IOMUX_TO_GPIO(GPIO2_21)) ? 1 : 0;
138 key_vals[7] = gpio_get_value(IOMUX_TO_GPIO(GPIO3_15)) ? 1 : 0;
139
140 //printk("<0>%04d key pressed: %d %d %d %d %d %d %d %d
",cnt++,key_vals[0],key_vals[1],key_vals[2],key_vals[3],key_vals[4],key_vals[5],key_vals[6],key_vals[7]);
141 */
142 }
143
144 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
145 {
146 printk("<0>function write!
");
147
148 return 1;
149 }
150
151 static int key_release(struct inode *inode, struct file *filp)
152 {
153 //canopen ++;
154 //atomic_inc(&canopen);
155 up(&canopen);
156 printk("<0>function release!
");
157 //释放中断
158 free_irq(IOMUX_TO_IRQ(GPIO2_21), &pins_desc[6]);
159 //free_irq(IOMUX_TO_IRQ(GPIO3_15),&pins_desc[7]);
160 free_irq(IOMUX_TO_IRQ(GPIO2_11), &pins_desc[5]);
161 free_irq(IOMUX_TO_IRQ(GPIO2_10), &pins_desc[4]);
162 free_irq(IOMUX_TO_IRQ(GPIO2_9), &pins_desc[3]);
163 //free_irq(IOMUX_TO_IRQ(GPIO2_8), &pins_desc[2]);
164 free_irq(IOMUX_TO_IRQ(GPIO2_7), &pins_desc[1]);
165 free_irq(IOMUX_TO_IRQ(GPIO2_6), &pins_desc[0]);
166 return 0;
167 }
168
169 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
170 {
171 int ret;
172 printk("<0>function ioctl!
");
173 switch (command) {
174 case key_input:
175 //设置所有的引脚为输入
176 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_21));
177 gpio_direction_input(IOMUX_TO_GPIO(GPIO3_15));
178 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_10));
179 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_11));
180 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_8));
181 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_9));
182 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_6));
183 gpio_direction_input(IOMUX_TO_GPIO(GPIO2_7));
184 printk("<0>have setting all pins to gpio input mod !
");
185 //设置GPIO引脚为上拉模式
186 mxc_iomux_set_pad(GPIO2_6, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
187 mxc_iomux_set_pad(GPIO2_7, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
188 //mxc_iomux_set_pad(GPIO2_8, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
189 mxc_iomux_set_pad(GPIO2_9, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
190 mxc_iomux_set_pad(GPIO2_10, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
191 mxc_iomux_set_pad(GPIO2_11, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
192 mxc_iomux_set_pad(GPIO2_21, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
193 //mxc_iomux_set_pad(GPIO3_15, PAD_CTL_HYS_SCHMITZ | PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_22K_PU);
194
195 //设置GPIO引脚中断 ,下降沿触发
196 request_irq(IOMUX_TO_IRQ(GPIO2_6), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_6", &pins_desc[0]);
197 request_irq(IOMUX_TO_IRQ(GPIO2_7), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_7", &pins_desc[1]);
198 request_irq(IOMUX_TO_IRQ(GPIO2_9), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_9", &pins_desc[3]);
199 request_irq(IOMUX_TO_IRQ(GPIO2_10), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_10", &pins_desc[4]);
200 request_irq(IOMUX_TO_IRQ(GPIO2_11), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_11", &pins_desc[5]);
201 request_irq(IOMUX_TO_IRQ(GPIO2_21), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_21", &pins_desc[6]);
202 //request_irq(IOMUX_TO_IRQ(GPIO3_15), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO3_15", &pins_desc[7]);
203 //request_irq(IOMUX_TO_IRQ(GPIO2_8), key_irq, IRQF_TRIGGER_FALLING, "key_GPIO2_8", &pins_desc[2]);
204 printk("<0>have setting all pins to gpio interrupt mod by IRQF_TRIGGER_FALLING !
");
205
206 break;
207 case version:
208 printk("<0>hello,the version is 0.1.0
");
209 break;
210 default:
211 printk("<0>command error
");
212 printk("<0>ioctl(fd, (unsigned int)command, (unsigned long) arg;
");
213 printk("<0>command: <key_input> <version>
");
214 return -1;
215 }
216 return 0;
217 }
218 static unsigned key_poll(struct file *file,poll_table *wait)
219 {
220 unsigned int mask = 0;
221 //程序不立即睡眠,而是继续等待
222 poll_wait(file,&key_interrupt_wait,wait);
223 //如果按键按下
224 if(ev_press)
225 mask |= POLLIN | POLLRDNORM;
226
227 return mask;
228 }
229
230 /* 这个结构是字符设备驱动程序的核心
231 * 当应用程序操作设备文件时所调用的open、read、write等函数,
232 * 最终会调用这个结构中指定的对应函数
233 */
234 static struct file_operations key_fops = {
235 .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
236 .open = key_open,
237 .read = key_read,
238 .write = key_write,
239 .release= key_release,
240 .ioctl = key_ioctl,
241 .poll = key_poll,
242 };
243
244 /*
245 * 执行insmod命令时就会调用这个函数
246 */
247 static int __init key_irq_init(void)
248 {
249 printk("<0>
Hello,this is %s module!
",Driver_NAME);
250 //register and mknod
251 major = register_chrdev(0,Driver_NAME,&key_fops);
252 drv_class = class_create(THIS_MODULE,Driver_NAME);
253 drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME); /*/dev/key_query*/
254 sema_init(&canopen,1); //初始化信号量为1
255
256 //set all pins to GPIO mod ALF5
257 mxc_request_iomux(GPIO2_21, MUX_CONFIG_ALT5);
258 mxc_request_iomux(GPIO3_15, MUX_CONFIG_ALT5);
259 mxc_request_iomux(GPIO2_10, MUX_CONFIG_ALT5);
260 mxc_request_iomux(GPIO2_11, MUX_CONFIG_ALT5);
261 mxc_request_iomux(GPIO2_8, MUX_CONFIG_ALT5);
262 mxc_request_iomux(GPIO2_9, MUX_CONFIG_ALT5);
263 mxc_request_iomux(GPIO2_6, MUX_CONFIG_ALT5);
264 mxc_request_iomux(GPIO2_7, MUX_CONFIG_ALT5);
265 //request IOMUX GPIO
266 gpio_request(IOMUX_TO_GPIO(GPIO2_21), "GPIO2_21");
267 gpio_request(IOMUX_TO_GPIO(GPIO3_15), "GPIO3_15");
268 gpio_request(IOMUX_TO_GPIO(GPIO2_10), "GPIO2_10");
269 gpio_request(IOMUX_TO_GPIO(GPIO2_11), "GPIO2_11");
270 gpio_request(IOMUX_TO_GPIO(GPIO2_8), "GPIO2_8");
271 gpio_request(IOMUX_TO_GPIO(GPIO2_9), "GPIO2_9");
272 gpio_request(IOMUX_TO_GPIO(GPIO2_6), "GPIO2_6");
273 gpio_request(IOMUX_TO_GPIO(GPIO2_7), "GPIO2_7");
274
275
276 return 0;
277 }
278
279 /*
280 * 执行rmmod命令时就会调用这个函数
281 */
282 static void __exit key_irq_exit(void)
283 {
284 printk("<0>
Goodbye,%s!
",Driver_NAME);
285
286 unregister_chrdev(major,Driver_NAME);
287 device_unregister(drv_class_dev);
288 class_destroy(drv_class);
289
290 /* free gpios */
291 mxc_free_iomux(GPIO2_21, MUX_CONFIG_ALT5);
292 mxc_free_iomux(GPIO3_15, MUX_CONFIG_ALT5);
293 mxc_free_iomux(GPIO2_10, MUX_CONFIG_ALT5);
294 mxc_free_iomux(GPIO2_11, MUX_CONFIG_ALT5);
295 mxc_free_iomux(GPIO2_8, MUX_CONFIG_ALT5);
296 mxc_free_iomux(GPIO2_9, MUX_CONFIG_ALT5);
297 mxc_free_iomux(GPIO2_6, MUX_CONFIG_ALT5);
298 mxc_free_iomux(GPIO2_7, MUX_CONFIG_ALT5);
299
300 gpio_free(IOMUX_TO_GPIO(GPIO2_21));
301 gpio_free(IOMUX_TO_GPIO(GPIO3_15));
302 gpio_free(IOMUX_TO_GPIO(GPIO2_10));
303 gpio_free(IOMUX_TO_GPIO(GPIO2_11));
304 gpio_free(IOMUX_TO_GPIO(GPIO2_8));
305 gpio_free(IOMUX_TO_GPIO(GPIO2_9));
306 gpio_free(IOMUX_TO_GPIO(GPIO2_6));
307 gpio_free(IOMUX_TO_GPIO(GPIO2_7));
308
309 }
310
311 /* 这两行指定驱动程序的初始化函数和卸载函数 */
312 module_init(key_irq_init);
313 module_exit(key_irq_exit);
314
315 /* 描述驱动程序的一些信息,不是必须的 */
316 MODULE_AUTHOR("Lover雪");
317 MODULE_VERSION("0.1.0");
318 MODULE_DESCRIPTION("IMX257 key Driver");
319 MODULE_LICENSE("GPL");