http://blog.csdn.net/vertor11/article/details/67634666
一:总体步骤
涉及文件:
a. 设备树文件:正确配置gpio复用及引脚属性。
b. 驱动模块文件:设置gpio中断相关操作。
二:实际操作
1.修改设备树
参考方法:
http://blog.csdn.net/vertor11/article/details/67633652
例如:将imx6ul的下图两个gpio设置为外部中断
设备树配置示例:
fsl,pins = < MX6UL_PAD_LCD_HSYNC__GPIO3_IO02 0x000010B0 MX6UL_PAD_LCD_VSYNC__GPIO3_IO03 0x000010B0 >;
2.驱动修改
参考方法:
http://blog.csdn.net/jiangbo_wei/article/details/9852659
http://www.wowotech.net/linux_kenrel/request_threaded_irq.html
http://blog.csdn.net/njuitjf/article/details/21475405
示例代码:
#include <linux/delay.h>#include <linux/if_arp.h>#include <linux/if_ether.h>#include <linux/interrupt.h>#include <linux/io.h>#include <linux/kernel.h>#include <linux/list.h>#include <linux/module.h>#include <linux/of.h>#include <linux/of_device.h>#include <linux/platform_device.h>#include <linux/gpio.h>#include <linux/irq.h>#include <linux/miscdevice.h>#include <linux/suspend.h>#include <linux/poll.h>#define MCU_WAKEUP_PIN 66static int wakeup_mcu_irq = 0;static irqreturn_t mcu_irq_handler(int irq, void *dev){ printk ("## mcu wake up! \n"); set_bit(8, &tbox_wakesoure); return IRQ_HANDLED;}static int wakesource_open(struct inode *inode, struct file *file){ return 0;}static int wakesource_release(struct inode *inode, struct file *file){ return 0;}static int wakesource_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){ if (!buf || count < 1) return 0; if (count > 4) count = 4; if (copy_to_user(buf, (void*)&tbox_wakesoure, count)) { printk(KERN_ERR"wakesource_read copy_to_user failed."); return -EFAULT; } return count;}static int wakesource_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){ tbox_wakesoure = 0; return count;}static const struct file_operations wakesource_fops = { .owner = THIS_MODULE, .open = wakesource_open, .release = wakesource_release, .read = wakesource_read, .write = wakesource_write,};static struct miscdevice wakesource_device = { .minor = MISC_DYNAMIC_MINOR, .name = "wakesource", .fops = &wakesource_fops,};static int __init gpio_init(void){ int ret; ret = misc_register(&wakesource_device); if (ret != 0) { printk(KERN_ERR "register wakesource_device miscdevice ret"); return ret; } if (0 == gpio_is_valid(MCU_WAKEUP_PIN)) { printk(KERN_ERR "mcu gpio is invalid!\n"); goto error; } ret = gpio_request_one(MCU_WAKEUP_PIN, GPIOF_IN, "mcupin"); if (ret < 0) { printk(KERN_ERR "Failed to request GPIO %d, ret %d\n", MCU_WAKEUP_PIN, ret); goto error; } wakeup_mcu_irq = gpio_to_irq(MCU_WAKEUP_PIN); if (wakeup_mcu_irq < 0) { ret = wakeup_mcu_irq; printk("Unable to get irq number for GPIO %d, ret %d\n", MCU_WAKEUP_PIN, ret); goto error; } ret = request_threaded_irq(wakeup_mcu_irq, mcu_irq_handler, NULL, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING|IRQF_NO_SUSPEND | IRQF_ONESHOT, "mcu", NULL); if (ret < 0) { printk(KERN_ERR "failed to register mcu irq %d!\n", wakeup_mcu_irq); goto freeirq; } ret = enable_irq_wake(wakeup_mcu_irq); if(ret) { printk(KERN_ERR "failed to set mcu gpio irq %d wake up!\n", wakeup_mcu_irq); goto freeirq; } printk("4g mcu wakeup driver probe sucsecc!\n"); return 0;freeirq: free_irq(wakeup_mcu_irq, NULL);error: misc_deregister(&wakesource_device); return ret;}module_init(gpio_init);static void __exit gpio_exit(void){ disable_irq_wake(wakeup_mcu_irq); free_irq(wakeup_mcu_irq, NULL); if (gpio_is_valid(MCU_WAKEUP_PIN)) gpio_free(MCU_WAKEUP_PIN); misc_deregister(&wakesource_device);}module_exit(gpio_exit);MODULE_AUTHOR("");MODULE_LICENSE("GPL v2");MODULE_DESCRIPTION("4g wakeup driver");