#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct gpio_key { int gpio; struct gpio_desc *gpiod; int flag; int irq; }; static struct gpio_key *gpio_keys; static irqreturn_t gpio_key_isr(int irq, void *dev_id) { struct gpio_key *key = dev_id; int value = gpiod_get_value(key->gpiod); printk("%s %s line %d: key %d is %d\r\n", __FILE__, __FUNCTION__, __LINE__, key->gpio, value); return IRQ_HANDLED; } static int interrupt_key_probe(struct platform_device *pdev) { int err; struct device_node *node = pdev->dev.of_node; int count; int i; enum of_gpio_flags flag; unsigned flags = GPIOF_IN; printk("%s %s %d\r\n", __FILE__, __FUNCTION__, __LINE__); count = of_gpio_count(node); if (count == 0) { printk("%s %s line %d: no gpio\r\n", __FILE__, __FUNCTION__, __LINE__); return -1; } gpio_keys = kzalloc(sizeof(struct gpio_key) * count, GFP_KERNEL); for (i = 0; i < count; i++) { gpio_keys[i].gpio = of_get_gpio_flags(node, i, &flag); if (gpio_keys[i].gpio < 0) { printk("%s %s line %d: of_get_gpio_flags failed\r\n", __FILE__, __FUNCTION__, __LINE__); return -1; } gpio_keys[i].gpiod = gpio_to_desc(gpio_keys[i].gpio); gpio_keys[i].flag = flag & OF_GPIO_ACTIVE_LOW; if (flag & OF_GPIO_ACTIVE_LOW) { flags |= GPIOF_ACTIVE_LOW; } err = devm_gpio_request_one(&pdev->dev, gpio_keys[i].gpio, flags, NULL); gpio_keys[i].irq = gpio_to_irq(gpio_keys[i].gpio); } for (i = 0; i < count; i++) { err = request_irq(gpio_keys[i].irq, gpio_key_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "gpio_key", &gpio_keys[i]); } return 0; } static int interrupt_key_remove(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; int count; int i; count = of_gpio_count(node); for (i = 0; i < count; i++) { free_irq(gpio_keys[i].irq, &gpio_keys[i]); } kfree(gpio_keys); printk("%s %s %d\r\n", __FILE__, __FUNCTION__, __LINE__); return 0; } static const struct of_device_id interrupt_key_of_match[] = { { .compatible = "jzh,interrupt-key", }, { }, }; static struct platform_driver interrupt_key_driver = { .probe = interrupt_key_probe, .remove = interrupt_key_remove, .driver = { .name = "interrupt-key", .of_match_table = of_match_ptr(interrupt_key_of_match), }, }; static int __init interrupt_key_init(void) { printk("%s %s %d\r\n", __FILE__, __FUNCTION__, __LINE__); return platform_driver_register(&interrupt_key_driver); } static void __exit interrupt_key_exit(void) { printk("%s %s %d\r\n", __FILE__, __FUNCTION__, __LINE__); platform_driver_unregister(&interrupt_key_driver); } module_init(interrupt_key_init); module_exit(interrupt_key_exit); MODULE_DESCRIPTION("Interrupt Key Driver"); MODULE_AUTHOR("jzhgonha@163.com"); MODULE_LICENSE("GPL");