博主寫(xiě)的 demo
博主下面給的是簡(jiǎn)化版,并且自測(cè)OK,分享給大家,以后如果需要可以copy xxx.c
#include < linux/module.h >
#include < linux/i2c.h >
#include < linux/interrupt.h >
#include < linux/delay.h >
#include < linux/uaccess.h >
#include < linux/pm.h >
#include < linux/slab.h >
#include < linux/sysctl.h >
#include < linux/proc_fs.h >
#include < linux/delay.h >
#include < linux/platform_device.h >
#include < linux/input.h >
#include < linux/gpio_keys.h >
#include < linux/workqueue.h >
#include < linux/gpio.h >
#include < linux/of.h >
#include < linux/of_platform.h >
#include < linux/of_gpio.h >
#include < linux/of_irq.h >
#include < linux/spinlock.h >
#include < linux/cdev.h >
static int gpionum = 0;
static int irqnum = 0;
static irqreturn_t my_handler(int irq, void *dev_id)
{
printk("%srn",__FUNCTION__);
return IRQ_HANDLED;
}
static int gpio_keys_probe(struct platform_device *pdev)
{
int ret = 0;
struct device_node *node = NULL;; /* 設(shè)備節(jié)點(diǎn)*/
node = of_find_compatible_node(NULL,NULL,"atkalpha-key");
if (node == NULL){
printk("%s:atkalpha-key node not find!rn",__FUNCTION__);
return -EINVAL;
}
/* 提取 GPIO */
gpionum = of_get_named_gpio(node,"key-gpio", 0);
if (gpionum < 0) {
printk("of_get_named_gpio can't get keyrn");
}
/* 初始化 key 所使用的 IO,并且設(shè)置成中斷模式 */
gpio_request(gpionum, "key-gpio");
gpio_direction_input(gpionum);
irqnum = gpio_to_irq(gpionum);
ret = request_irq(irqnum,my_handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "my-key", NULL);
if(ret < 0){
printk("irq %d request failed!rn", irqnum);
return -EFAULT;
}
return 0;
}
static const struct of_device_id gpio_keys_of_match[] = {
{ .compatible = "atkalpha-key", },
{ },
};
MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
static int gpio_keys_remove(struct platform_device *pdev)
{
return 0;
}
static int gpio_keys_suspend(struct device *dev)
{
printk("%srn",__FUNCTION__);
enable_irq_wake(irqnum);
return 0;
}
static int gpio_keys_resume(struct device *dev)
{
printk("%srn",__FUNCTION__);
disable_irq_wake(irqnum);
return 0;
}
static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = gpio_keys_remove,
.driver = {
.name = "my-key",
.pm = &gpio_keys_pm_ops,
.of_match_table = of_match_ptr(gpio_keys_of_match),
}
};
static int __init gpio_keys_init(void)
{
return platform_driver_register(&gpio_keys_device_driver);
}
static void __exit gpio_keys_exit(void)
{
platform_driver_unregister(&gpio_keys_device_driver);
}
module_init(gpio_keys_init);
module_exit(gpio_keys_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jason");
MODULE_DESCRIPTION("Keyboard driver for GPIOs");
MODULE_ALIAS("platform:gpio-keys");
xxx.dts
key {
#address-cells = < 1 >;
#size-cells = < 1 >;
compatible = "atkalpha-key";
key-gpio = < &gpio1 18 GPIO_ACTIVE_LOW >; /* KEY0 */
interrupt-parent = < &gpio1 >;
interrupts = < 18 IRQ_TYPE_EDGE_BOTH >; /* FALLING RISING */
gpio-key,wakeup;
status = "okay";
};
最后再總結(jié)一下:中斷喚醒系統(tǒng)和普通的驅(qū)動(dòng)區(qū)別在于,多了兩個(gè)函數(shù):suspend 和 resume,在suspend 函數(shù)中,調(diào)用 enable_irq_wake,表示該中斷號(hào)在系統(tǒng)休眠時(shí)也是 enable 狀態(tài),可以觸發(fā)中斷。在 resume 函數(shù)中,調(diào)用 disable_irq_wake ,恢復(fù)原始的中斷觸發(fā)路徑。
然后使用 SIMPLE_DEV_PM_OPS 宏將 suspend 和 resume 函數(shù)注冊(cè)到 gpio_keys_pm_ops 操作集,最終由 platform 注冊(cè)到系統(tǒng)中。這樣完成后,系統(tǒng)休眠過(guò)程中就會(huì)調(diào)用到設(shè)備注冊(cè)的 suspend,系統(tǒng)喚醒過(guò)程中就會(huì)調(diào)用設(shè)備注冊(cè)的 resume 函數(shù)。
note:該 demo 只用來(lái)喚醒系統(tǒng),如果你的中斷是在 I2C 等設(shè)備驅(qū)動(dòng)中,喚醒系統(tǒng)后要立刻在中斷處理函數(shù)中進(jìn)行 I2C 通信,寫(xiě)法不太一樣,但是框架相同。
另外,該驅(qū)動(dòng)的中斷處理函數(shù)中沒(méi)做什么東西,因此喚醒后執(zhí)行完中斷處理函數(shù)后又會(huì)睡過(guò)去。如果你想要該中斷喚醒系統(tǒng)后讓系統(tǒng)一直處于喚醒狀態(tài),請(qǐng)?jiān)谥袛嗵幚砗瘮?shù)中使用 __pm_stay_awake() 和__pm_relax()函數(shù)。
-
嵌入式
+關(guān)注
關(guān)注
5060文章
18980瀏覽量
302252 -
Linux
+關(guān)注
關(guān)注
87文章
11215瀏覽量
208742 -
系統(tǒng)
+關(guān)注
關(guān)注
1文章
1006瀏覽量
21297
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論