1.实现设备树
//需注意在Jetson 中AON_GPIO 不支持中断获取,使用中断必须使用MAIN_GPIO
amov-gpios{
compatible ="amov-keys";
gpios-key = <&tegra_main_gpio TEGRA194_MAIN_GPIO(Q, 2) GPIO_ACTIVE_HIGH>;
status = "okay";
};
2.实现按键驱动
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.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/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
#include <linux/of_gpio.h>
#include <linux/time.h>
#include <linux/timer.h>
struct btn_resource {
int gpio;
int mode;
int amov_irq;
char code;
};
static struct btn_resource *gpio_info;
struct input_dev *btn_input = NULL;
static struct delayed_work delay_amov;
static void delay_work_func(struct work_struct *work)
{
int state;
state =gpio_get_value(gpio_info->gpio);
input_event(btn_input, EV_KEY,
gpio_info->code, !state);
input_sync(btn_input);
}
static irqreturn_t button_isr(int irq, void *dev)
{
gpio_info = (struct btn_resource *)dev;
schedule_delayed_work(&delay_amov, jiffies+HZ/100);
return IRQ_HANDLED;
}
static const struct of_device_id gpio_keys_of_match[] = {
{ .compatible = "amov-keys", },
{ },
};
MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
MODULE_INFO(intree, "Y");
static int gpio_keys_probe(struct platform_device *pdev)
{
int ret;
int gpio;
enum of_gpio_flags flag;
struct device_node *amov_gpio_node = pdev->dev.of_node;
gpio_info =devm_kzalloc(&pdev->dev,sizeof(struct btn_resource *), GFP_KERNEL);
if (!gpio_info) {
return -ENOMEM;
}
gpio = of_get_named_gpio_flags(amov_gpio_node, "gpios-key", 0, &flag);
if (!gpio_is_valid(gpio))
{
goto ERROR;
}
gpio_info->gpio=gpio;
gpio_info->amov_irq=gpio_to_irq(gpio);
gpio_info->code=KEY_UP;
if(gpio_info->amov_irq){
if (gpio_request(gpio, "amov-irq-gpio"))
{
goto ERROR;
}
ret = request_irq(gpio_info->amov_irq, button_isr,IRQ_TYPE_EDGE_BOTH|IRQF_SHARED, "amov-gpio", gpio_info);
}
btn_input = input_allocate_device();
btn_input->name = "amov_buttons";
set_bit(EV_KEY, btn_input->evbit);
set_bit(EV_SYN, btn_input->evbit);
set_bit(EV_REP, btn_input->evbit);
set_bit(KEY_UP, btn_input->keybit);
ret = input_register_device(btn_input);
INIT_DELAYED_WORK(&delay_amov, delay_work_func);
return 0;
ERROR:
dev_err(&pdev->dev,"amov buttons error \n ");
gpio_free(gpio);
return -1;
}
static void gpio_keys_shutdown(struct platform_device *pdev)
{
}
int btn_remove(struct platform_device *pdev)
{
free_irq(gpio_info->amov_irq,gpio_info);
gpio_free(gpio_info->gpio);
input_unregister_device(btn_input);
input_free_device(btn_input);
return 0;
}
static int __maybe_unused gpio_keys_suspend(struct device *dev)
{
return 0;
}
static int __maybe_unused gpio_keys_resume(struct device *dev)
{
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,
.shutdown = gpio_keys_shutdown,
.remove = btn_remove,
.driver = {
.name = "amov-keys",
.pm = &gpio_keys_pm_ops,
.of_match_table = gpio_keys_of_match,
}
};
static int btn_init(void)
{
platform_driver_register(&gpio_keys_device_driver);
return 0;
}
static void btn_exit(void)
{
platform_driver_unregister(&gpio_keys_device_driver);
}
module_init(btn_init);
module_exit(btn_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("hj");