178a56aabSPhil Blundell /* 278a56aabSPhil Blundell * Driver for keys on GPIO lines capable of generating interrupts. 378a56aabSPhil Blundell * 478a56aabSPhil Blundell * Copyright 2005 Phil Blundell 5fd05d089SDavid Jander * Copyright 2010, 2011 David Jander <david@protonic.nl> 678a56aabSPhil Blundell * 778a56aabSPhil Blundell * This program is free software; you can redistribute it and/or modify 878a56aabSPhil Blundell * it under the terms of the GNU General Public License version 2 as 978a56aabSPhil Blundell * published by the Free Software Foundation. 1078a56aabSPhil Blundell */ 1178a56aabSPhil Blundell 1278a56aabSPhil Blundell #include <linux/module.h> 1378a56aabSPhil Blundell 1478a56aabSPhil Blundell #include <linux/init.h> 1578a56aabSPhil Blundell #include <linux/fs.h> 1678a56aabSPhil Blundell #include <linux/interrupt.h> 1778a56aabSPhil Blundell #include <linux/irq.h> 1878a56aabSPhil Blundell #include <linux/sched.h> 1978a56aabSPhil Blundell #include <linux/pm.h> 205a0e3ad6STejun Heo #include <linux/slab.h> 2178a56aabSPhil Blundell #include <linux/sysctl.h> 2278a56aabSPhil Blundell #include <linux/proc_fs.h> 2378a56aabSPhil Blundell #include <linux/delay.h> 2478a56aabSPhil Blundell #include <linux/platform_device.h> 2578a56aabSPhil Blundell #include <linux/input.h> 2649015beeSDavid Brownell #include <linux/gpio_keys.h> 27da0d03feSJani Nikula #include <linux/workqueue.h> 28111bc59cSBen Dooks #include <linux/gpio.h> 295feeca3cSGeert Uytterhoeven #include <linux/gpio/consumer.h> 30415a4caaSSachin Kamat #include <linux/of.h> 31f2d347ffSAlexander Stein #include <linux/of_irq.h> 32d8ee4a1cSLaxman Dewangan #include <linux/spinlock.h> 33*83fc580dSJeffy Chen #include <dt-bindings/input/gpio-keys.h> 3478a56aabSPhil Blundell 35a33466e3SDmitry Baryshkov struct gpio_button_data { 36d9080921SDmitry Torokhov const struct gpio_keys_button *button; 37a33466e3SDmitry Baryshkov struct input_dev *input; 385feeca3cSGeert Uytterhoeven struct gpio_desc *gpiod; 398ed92556SDmitry Torokhov 4083e4947aSHans de Goede unsigned short *code; 4183e4947aSHans de Goede 428ed92556SDmitry Torokhov struct timer_list release_timer; 438ed92556SDmitry Torokhov unsigned int release_delay; /* in msecs, for IRQ-only buttons */ 448ed92556SDmitry Torokhov 458ed92556SDmitry Torokhov struct delayed_work work; 468ed92556SDmitry Torokhov unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */ 478ed92556SDmitry Torokhov 48d8ee4a1cSLaxman Dewangan unsigned int irq; 49*83fc580dSJeffy Chen unsigned int wakeup_trigger_type; 50d8ee4a1cSLaxman Dewangan spinlock_t lock; 519e3af04fSMika Westerberg bool disabled; 52d8ee4a1cSLaxman Dewangan bool key_pressed; 530f107573SJoseph Lo bool suspended; 54a33466e3SDmitry Baryshkov }; 55a33466e3SDmitry Baryshkov 56a33466e3SDmitry Baryshkov struct gpio_keys_drvdata { 57219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata; 58a33466e3SDmitry Baryshkov struct input_dev *input; 599e3af04fSMika Westerberg struct mutex disable_lock; 6083e4947aSHans de Goede unsigned short *keymap; 61a33466e3SDmitry Baryshkov struct gpio_button_data data[0]; 62a33466e3SDmitry Baryshkov }; 63a33466e3SDmitry Baryshkov 649e3af04fSMika Westerberg /* 659e3af04fSMika Westerberg * SYSFS interface for enabling/disabling keys and switches: 669e3af04fSMika Westerberg * 679e3af04fSMika Westerberg * There are 4 attributes under /sys/devices/platform/gpio-keys/ 689e3af04fSMika Westerberg * keys [ro] - bitmap of keys (EV_KEY) which can be 699e3af04fSMika Westerberg * disabled 709e3af04fSMika Westerberg * switches [ro] - bitmap of switches (EV_SW) which can be 719e3af04fSMika Westerberg * disabled 729e3af04fSMika Westerberg * disabled_keys [rw] - bitmap of keys currently disabled 739e3af04fSMika Westerberg * disabled_switches [rw] - bitmap of switches currently disabled 749e3af04fSMika Westerberg * 759e3af04fSMika Westerberg * Userland can change these values and hence disable event generation 769e3af04fSMika Westerberg * for each key (or switch). Disabling a key means its interrupt line 779e3af04fSMika Westerberg * is disabled. 789e3af04fSMika Westerberg * 799e3af04fSMika Westerberg * For example, if we have following switches set up as gpio-keys: 809e3af04fSMika Westerberg * SW_DOCK = 5 819e3af04fSMika Westerberg * SW_CAMERA_LENS_COVER = 9 829e3af04fSMika Westerberg * SW_KEYPAD_SLIDE = 10 839e3af04fSMika Westerberg * SW_FRONT_PROXIMITY = 11 849e3af04fSMika Westerberg * This is read from switches: 859e3af04fSMika Westerberg * 11-9,5 869e3af04fSMika Westerberg * Next we want to disable proximity (11) and dock (5), we write: 879e3af04fSMika Westerberg * 11,5 889e3af04fSMika Westerberg * to file disabled_switches. Now proximity and dock IRQs are disabled. 899e3af04fSMika Westerberg * This can be verified by reading the file disabled_switches: 909e3af04fSMika Westerberg * 11,5 919e3af04fSMika Westerberg * If we now want to enable proximity (11) switch we write: 929e3af04fSMika Westerberg * 5 939e3af04fSMika Westerberg * to disabled_switches. 949e3af04fSMika Westerberg * 959e3af04fSMika Westerberg * We can disable only those keys which don't allow sharing the irq. 969e3af04fSMika Westerberg */ 979e3af04fSMika Westerberg 989e3af04fSMika Westerberg /** 999e3af04fSMika Westerberg * get_n_events_by_type() - returns maximum number of events per @type 1009e3af04fSMika Westerberg * @type: type of button (%EV_KEY, %EV_SW) 1019e3af04fSMika Westerberg * 1029e3af04fSMika Westerberg * Return value of this function can be used to allocate bitmap 1039e3af04fSMika Westerberg * large enough to hold all bits for given type. 1049e3af04fSMika Westerberg */ 1058679ee42SDmitry Torokhov static int get_n_events_by_type(int type) 1069e3af04fSMika Westerberg { 1079e3af04fSMika Westerberg BUG_ON(type != EV_SW && type != EV_KEY); 1089e3af04fSMika Westerberg 1099e3af04fSMika Westerberg return (type == EV_KEY) ? KEY_CNT : SW_CNT; 1109e3af04fSMika Westerberg } 1119e3af04fSMika Westerberg 1129e3af04fSMika Westerberg /** 1138679ee42SDmitry Torokhov * get_bm_events_by_type() - returns bitmap of supported events per @type 1148679ee42SDmitry Torokhov * @input: input device from which bitmap is retrieved 1158679ee42SDmitry Torokhov * @type: type of button (%EV_KEY, %EV_SW) 1168679ee42SDmitry Torokhov * 1178679ee42SDmitry Torokhov * Return value of this function can be used to allocate bitmap 1188679ee42SDmitry Torokhov * large enough to hold all bits for given type. 1198679ee42SDmitry Torokhov */ 1208679ee42SDmitry Torokhov static const unsigned long *get_bm_events_by_type(struct input_dev *dev, 1218679ee42SDmitry Torokhov int type) 1228679ee42SDmitry Torokhov { 1238679ee42SDmitry Torokhov BUG_ON(type != EV_SW && type != EV_KEY); 1248679ee42SDmitry Torokhov 1258679ee42SDmitry Torokhov return (type == EV_KEY) ? dev->keybit : dev->swbit; 1268679ee42SDmitry Torokhov } 1278679ee42SDmitry Torokhov 1288679ee42SDmitry Torokhov /** 1299e3af04fSMika Westerberg * gpio_keys_disable_button() - disables given GPIO button 1309e3af04fSMika Westerberg * @bdata: button data for button to be disabled 1319e3af04fSMika Westerberg * 1329e3af04fSMika Westerberg * Disables button pointed by @bdata. This is done by masking 1339e3af04fSMika Westerberg * IRQ line. After this function is called, button won't generate 1349e3af04fSMika Westerberg * input events anymore. Note that one can only disable buttons 1359e3af04fSMika Westerberg * that don't share IRQs. 1369e3af04fSMika Westerberg * 1379e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1389e3af04fSMika Westerberg * this function to avoid races when concurrent threads are 1399e3af04fSMika Westerberg * disabling buttons at the same time. 1409e3af04fSMika Westerberg */ 1419e3af04fSMika Westerberg static void gpio_keys_disable_button(struct gpio_button_data *bdata) 1429e3af04fSMika Westerberg { 1439e3af04fSMika Westerberg if (!bdata->disabled) { 1449e3af04fSMika Westerberg /* 1458ed92556SDmitry Torokhov * Disable IRQ and associated timer/work structure. 1469e3af04fSMika Westerberg */ 147d8ee4a1cSLaxman Dewangan disable_irq(bdata->irq); 1488ed92556SDmitry Torokhov 1495feeca3cSGeert Uytterhoeven if (bdata->gpiod) 1508ed92556SDmitry Torokhov cancel_delayed_work_sync(&bdata->work); 1518ed92556SDmitry Torokhov else 1528ed92556SDmitry Torokhov del_timer_sync(&bdata->release_timer); 1539e3af04fSMika Westerberg 1549e3af04fSMika Westerberg bdata->disabled = true; 1559e3af04fSMika Westerberg } 1569e3af04fSMika Westerberg } 1579e3af04fSMika Westerberg 1589e3af04fSMika Westerberg /** 1599e3af04fSMika Westerberg * gpio_keys_enable_button() - enables given GPIO button 1609e3af04fSMika Westerberg * @bdata: button data for button to be disabled 1619e3af04fSMika Westerberg * 1629e3af04fSMika Westerberg * Enables given button pointed by @bdata. 1639e3af04fSMika Westerberg * 1649e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1659e3af04fSMika Westerberg * this function to avoid races with concurrent threads trying 1669e3af04fSMika Westerberg * to enable the same button at the same time. 1679e3af04fSMika Westerberg */ 1689e3af04fSMika Westerberg static void gpio_keys_enable_button(struct gpio_button_data *bdata) 1699e3af04fSMika Westerberg { 1709e3af04fSMika Westerberg if (bdata->disabled) { 171d8ee4a1cSLaxman Dewangan enable_irq(bdata->irq); 1729e3af04fSMika Westerberg bdata->disabled = false; 1739e3af04fSMika Westerberg } 1749e3af04fSMika Westerberg } 1759e3af04fSMika Westerberg 1769e3af04fSMika Westerberg /** 1779e3af04fSMika Westerberg * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons 1789e3af04fSMika Westerberg * @ddata: pointer to drvdata 1799e3af04fSMika Westerberg * @buf: buffer where stringified bitmap is written 1809e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 1819e3af04fSMika Westerberg * @only_disabled: does caller want only those buttons that are 1829e3af04fSMika Westerberg * currently disabled or all buttons that can be 1839e3af04fSMika Westerberg * disabled 1849e3af04fSMika Westerberg * 1859e3af04fSMika Westerberg * This function writes buttons that can be disabled to @buf. If 1869e3af04fSMika Westerberg * @only_disabled is true, then @buf contains only those buttons 1879e3af04fSMika Westerberg * that are currently disabled. Returns 0 on success or negative 1889e3af04fSMika Westerberg * errno on failure. 1899e3af04fSMika Westerberg */ 1909e3af04fSMika Westerberg static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, 1919e3af04fSMika Westerberg char *buf, unsigned int type, 1929e3af04fSMika Westerberg bool only_disabled) 1939e3af04fSMika Westerberg { 1949e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 1959e3af04fSMika Westerberg unsigned long *bits; 1969e3af04fSMika Westerberg ssize_t ret; 1979e3af04fSMika Westerberg int i; 1989e3af04fSMika Westerberg 1999e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 2009e3af04fSMika Westerberg if (!bits) 2019e3af04fSMika Westerberg return -ENOMEM; 2029e3af04fSMika Westerberg 203219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2049e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2059e3af04fSMika Westerberg 2069e3af04fSMika Westerberg if (bdata->button->type != type) 2079e3af04fSMika Westerberg continue; 2089e3af04fSMika Westerberg 2099e3af04fSMika Westerberg if (only_disabled && !bdata->disabled) 2109e3af04fSMika Westerberg continue; 2119e3af04fSMika Westerberg 21283e4947aSHans de Goede __set_bit(*bdata->code, bits); 2139e3af04fSMika Westerberg } 2149e3af04fSMika Westerberg 2150b480037STejun Heo ret = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", n_events, bits); 2169e3af04fSMika Westerberg buf[ret++] = '\n'; 2179e3af04fSMika Westerberg buf[ret] = '\0'; 2189e3af04fSMika Westerberg 2199e3af04fSMika Westerberg kfree(bits); 2209e3af04fSMika Westerberg 2219e3af04fSMika Westerberg return ret; 2229e3af04fSMika Westerberg } 2239e3af04fSMika Westerberg 2249e3af04fSMika Westerberg /** 2259e3af04fSMika Westerberg * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap 2269e3af04fSMika Westerberg * @ddata: pointer to drvdata 2279e3af04fSMika Westerberg * @buf: buffer from userspace that contains stringified bitmap 2289e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 2299e3af04fSMika Westerberg * 2309e3af04fSMika Westerberg * This function parses stringified bitmap from @buf and disables/enables 231a16ca239SDmitry Torokhov * GPIO buttons accordingly. Returns 0 on success and negative error 2329e3af04fSMika Westerberg * on failure. 2339e3af04fSMika Westerberg */ 2349e3af04fSMika Westerberg static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, 2359e3af04fSMika Westerberg const char *buf, unsigned int type) 2369e3af04fSMika Westerberg { 2379e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 2388679ee42SDmitry Torokhov const unsigned long *bitmap = get_bm_events_by_type(ddata->input, type); 2399e3af04fSMika Westerberg unsigned long *bits; 2409e3af04fSMika Westerberg ssize_t error; 2419e3af04fSMika Westerberg int i; 2429e3af04fSMika Westerberg 2439e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 2449e3af04fSMika Westerberg if (!bits) 2459e3af04fSMika Westerberg return -ENOMEM; 2469e3af04fSMika Westerberg 2479e3af04fSMika Westerberg error = bitmap_parselist(buf, bits, n_events); 2489e3af04fSMika Westerberg if (error) 2499e3af04fSMika Westerberg goto out; 2509e3af04fSMika Westerberg 2519e3af04fSMika Westerberg /* First validate */ 2528679ee42SDmitry Torokhov if (!bitmap_subset(bits, bitmap, n_events)) { 2538679ee42SDmitry Torokhov error = -EINVAL; 2548679ee42SDmitry Torokhov goto out; 2558679ee42SDmitry Torokhov } 2568679ee42SDmitry Torokhov 257219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2589e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2599e3af04fSMika Westerberg 2609e3af04fSMika Westerberg if (bdata->button->type != type) 2619e3af04fSMika Westerberg continue; 2629e3af04fSMika Westerberg 26383e4947aSHans de Goede if (test_bit(*bdata->code, bits) && 2649e3af04fSMika Westerberg !bdata->button->can_disable) { 2659e3af04fSMika Westerberg error = -EINVAL; 2669e3af04fSMika Westerberg goto out; 2679e3af04fSMika Westerberg } 2689e3af04fSMika Westerberg } 2699e3af04fSMika Westerberg 2709e3af04fSMika Westerberg mutex_lock(&ddata->disable_lock); 2719e3af04fSMika Westerberg 272219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2739e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2749e3af04fSMika Westerberg 2759e3af04fSMika Westerberg if (bdata->button->type != type) 2769e3af04fSMika Westerberg continue; 2779e3af04fSMika Westerberg 27883e4947aSHans de Goede if (test_bit(*bdata->code, bits)) 2799e3af04fSMika Westerberg gpio_keys_disable_button(bdata); 2809e3af04fSMika Westerberg else 2819e3af04fSMika Westerberg gpio_keys_enable_button(bdata); 2829e3af04fSMika Westerberg } 2839e3af04fSMika Westerberg 2849e3af04fSMika Westerberg mutex_unlock(&ddata->disable_lock); 2859e3af04fSMika Westerberg 2869e3af04fSMika Westerberg out: 2879e3af04fSMika Westerberg kfree(bits); 2889e3af04fSMika Westerberg return error; 2899e3af04fSMika Westerberg } 2909e3af04fSMika Westerberg 2919e3af04fSMika Westerberg #define ATTR_SHOW_FN(name, type, only_disabled) \ 2929e3af04fSMika Westerberg static ssize_t gpio_keys_show_##name(struct device *dev, \ 2939e3af04fSMika Westerberg struct device_attribute *attr, \ 2949e3af04fSMika Westerberg char *buf) \ 2959e3af04fSMika Westerberg { \ 2969e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 2979e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 2989e3af04fSMika Westerberg \ 2999e3af04fSMika Westerberg return gpio_keys_attr_show_helper(ddata, buf, \ 3009e3af04fSMika Westerberg type, only_disabled); \ 3019e3af04fSMika Westerberg } 3029e3af04fSMika Westerberg 3039e3af04fSMika Westerberg ATTR_SHOW_FN(keys, EV_KEY, false); 3049e3af04fSMika Westerberg ATTR_SHOW_FN(switches, EV_SW, false); 3059e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_keys, EV_KEY, true); 3069e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_switches, EV_SW, true); 3079e3af04fSMika Westerberg 3089e3af04fSMika Westerberg /* 3099e3af04fSMika Westerberg * ATTRIBUTES: 3109e3af04fSMika Westerberg * 3119e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/keys [ro] 3129e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/switches [ro] 3139e3af04fSMika Westerberg */ 3149e3af04fSMika Westerberg static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL); 3159e3af04fSMika Westerberg static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL); 3169e3af04fSMika Westerberg 3179e3af04fSMika Westerberg #define ATTR_STORE_FN(name, type) \ 3189e3af04fSMika Westerberg static ssize_t gpio_keys_store_##name(struct device *dev, \ 3199e3af04fSMika Westerberg struct device_attribute *attr, \ 3209e3af04fSMika Westerberg const char *buf, \ 3219e3af04fSMika Westerberg size_t count) \ 3229e3af04fSMika Westerberg { \ 3239e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 3249e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 3259e3af04fSMika Westerberg ssize_t error; \ 3269e3af04fSMika Westerberg \ 3279e3af04fSMika Westerberg error = gpio_keys_attr_store_helper(ddata, buf, type); \ 3289e3af04fSMika Westerberg if (error) \ 3299e3af04fSMika Westerberg return error; \ 3309e3af04fSMika Westerberg \ 3319e3af04fSMika Westerberg return count; \ 3329e3af04fSMika Westerberg } 3339e3af04fSMika Westerberg 3349e3af04fSMika Westerberg ATTR_STORE_FN(disabled_keys, EV_KEY); 3359e3af04fSMika Westerberg ATTR_STORE_FN(disabled_switches, EV_SW); 3369e3af04fSMika Westerberg 3379e3af04fSMika Westerberg /* 3389e3af04fSMika Westerberg * ATTRIBUTES: 3399e3af04fSMika Westerberg * 3409e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disabled_keys [rw] 3419e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disables_switches [rw] 3429e3af04fSMika Westerberg */ 3439e3af04fSMika Westerberg static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO, 3449e3af04fSMika Westerberg gpio_keys_show_disabled_keys, 3459e3af04fSMika Westerberg gpio_keys_store_disabled_keys); 3469e3af04fSMika Westerberg static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO, 3479e3af04fSMika Westerberg gpio_keys_show_disabled_switches, 3489e3af04fSMika Westerberg gpio_keys_store_disabled_switches); 3499e3af04fSMika Westerberg 3509e3af04fSMika Westerberg static struct attribute *gpio_keys_attrs[] = { 3519e3af04fSMika Westerberg &dev_attr_keys.attr, 3529e3af04fSMika Westerberg &dev_attr_switches.attr, 3539e3af04fSMika Westerberg &dev_attr_disabled_keys.attr, 3549e3af04fSMika Westerberg &dev_attr_disabled_switches.attr, 3559e3af04fSMika Westerberg NULL, 3569e3af04fSMika Westerberg }; 3579e3af04fSMika Westerberg 35821563a7eSArvind Yadav static const struct attribute_group gpio_keys_attr_group = { 3599e3af04fSMika Westerberg .attrs = gpio_keys_attrs, 3609e3af04fSMika Westerberg }; 3619e3af04fSMika Westerberg 362d8ee4a1cSLaxman Dewangan static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) 36378a56aabSPhil Blundell { 364d9080921SDmitry Torokhov const struct gpio_keys_button *button = bdata->button; 365ce25d7e9SUwe Kleine-König struct input_dev *input = bdata->input; 36684767d00SRoman Moravcik unsigned int type = button->type ?: EV_KEY; 3675feeca3cSGeert Uytterhoeven int state; 36884767d00SRoman Moravcik 3695feeca3cSGeert Uytterhoeven state = gpiod_get_value_cansleep(bdata->gpiod); 37077fa0554SBjorn Andersson if (state < 0) { 3715feeca3cSGeert Uytterhoeven dev_err(input->dev.parent, 3725feeca3cSGeert Uytterhoeven "failed to get gpio state: %d\n", state); 37377fa0554SBjorn Andersson return; 37477fa0554SBjorn Andersson } 37577fa0554SBjorn Andersson 37692a47674SAlexander Stein if (type == EV_ABS) { 37792a47674SAlexander Stein if (state) 37892a47674SAlexander Stein input_event(input, type, button->code, button->value); 37992a47674SAlexander Stein } else { 38083e4947aSHans de Goede input_event(input, type, *bdata->code, state); 38192a47674SAlexander Stein } 38278a56aabSPhil Blundell input_sync(input); 383a33466e3SDmitry Baryshkov } 384a33466e3SDmitry Baryshkov 385d8ee4a1cSLaxman Dewangan static void gpio_keys_gpio_work_func(struct work_struct *work) 3866ee88d71SDaniel Mack { 3876ee88d71SDaniel Mack struct gpio_button_data *bdata = 3888ed92556SDmitry Torokhov container_of(work, struct gpio_button_data, work.work); 3896ee88d71SDaniel Mack 390d8ee4a1cSLaxman Dewangan gpio_keys_gpio_report_event(bdata); 3912fba26c6SNeilBrown 3922fba26c6SNeilBrown if (bdata->button->wakeup) 3932fba26c6SNeilBrown pm_relax(bdata->input->dev.parent); 3946ee88d71SDaniel Mack } 3956ee88d71SDaniel Mack 396d8ee4a1cSLaxman Dewangan static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) 397a33466e3SDmitry Baryshkov { 39857ffe9d5SUwe Kleine-König struct gpio_button_data *bdata = dev_id; 399a33466e3SDmitry Baryshkov 400d8ee4a1cSLaxman Dewangan BUG_ON(irq != bdata->irq); 401a33466e3SDmitry Baryshkov 4020f107573SJoseph Lo if (bdata->button->wakeup) { 4030f107573SJoseph Lo const struct gpio_keys_button *button = bdata->button; 4040f107573SJoseph Lo 4052fba26c6SNeilBrown pm_stay_awake(bdata->input->dev.parent); 4060f107573SJoseph Lo if (bdata->suspended && 4070f107573SJoseph Lo (button->type == 0 || button->type == EV_KEY)) { 4080f107573SJoseph Lo /* 4090f107573SJoseph Lo * Simulate wakeup key press in case the key has 4100f107573SJoseph Lo * already released by the time we got interrupt 4110f107573SJoseph Lo * handler to run. 4120f107573SJoseph Lo */ 4130f107573SJoseph Lo input_report_key(bdata->input, button->code, 1); 4140f107573SJoseph Lo } 4150f107573SJoseph Lo } 4168ed92556SDmitry Torokhov 4178ed92556SDmitry Torokhov mod_delayed_work(system_wq, 4188ed92556SDmitry Torokhov &bdata->work, 4198ed92556SDmitry Torokhov msecs_to_jiffies(bdata->software_debounce)); 420a33466e3SDmitry Baryshkov 4211164ec1aSDavid Brownell return IRQ_HANDLED; 42278a56aabSPhil Blundell } 42378a56aabSPhil Blundell 42482565a12Sstephen lu static void gpio_keys_irq_timer(struct timer_list *t) 425d8ee4a1cSLaxman Dewangan { 42682565a12Sstephen lu struct gpio_button_data *bdata = from_timer(bdata, t, release_timer); 427d8ee4a1cSLaxman Dewangan struct input_dev *input = bdata->input; 428d8ee4a1cSLaxman Dewangan unsigned long flags; 429d8ee4a1cSLaxman Dewangan 430d8ee4a1cSLaxman Dewangan spin_lock_irqsave(&bdata->lock, flags); 431d8ee4a1cSLaxman Dewangan if (bdata->key_pressed) { 43283e4947aSHans de Goede input_event(input, EV_KEY, *bdata->code, 0); 433d8ee4a1cSLaxman Dewangan input_sync(input); 434d8ee4a1cSLaxman Dewangan bdata->key_pressed = false; 435d8ee4a1cSLaxman Dewangan } 436d8ee4a1cSLaxman Dewangan spin_unlock_irqrestore(&bdata->lock, flags); 437d8ee4a1cSLaxman Dewangan } 438d8ee4a1cSLaxman Dewangan 439d8ee4a1cSLaxman Dewangan static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) 440d8ee4a1cSLaxman Dewangan { 441d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = dev_id; 442d8ee4a1cSLaxman Dewangan struct input_dev *input = bdata->input; 443d8ee4a1cSLaxman Dewangan unsigned long flags; 444d8ee4a1cSLaxman Dewangan 445d8ee4a1cSLaxman Dewangan BUG_ON(irq != bdata->irq); 446d8ee4a1cSLaxman Dewangan 447d8ee4a1cSLaxman Dewangan spin_lock_irqsave(&bdata->lock, flags); 448d8ee4a1cSLaxman Dewangan 449d8ee4a1cSLaxman Dewangan if (!bdata->key_pressed) { 4502fba26c6SNeilBrown if (bdata->button->wakeup) 4512fba26c6SNeilBrown pm_wakeup_event(bdata->input->dev.parent, 0); 4522fba26c6SNeilBrown 45383e4947aSHans de Goede input_event(input, EV_KEY, *bdata->code, 1); 454d8ee4a1cSLaxman Dewangan input_sync(input); 455d8ee4a1cSLaxman Dewangan 4568ed92556SDmitry Torokhov if (!bdata->release_delay) { 45783e4947aSHans de Goede input_event(input, EV_KEY, *bdata->code, 0); 458d8ee4a1cSLaxman Dewangan input_sync(input); 459d8ee4a1cSLaxman Dewangan goto out; 460d8ee4a1cSLaxman Dewangan } 461d8ee4a1cSLaxman Dewangan 462d8ee4a1cSLaxman Dewangan bdata->key_pressed = true; 463d8ee4a1cSLaxman Dewangan } 464d8ee4a1cSLaxman Dewangan 4658ed92556SDmitry Torokhov if (bdata->release_delay) 4668ed92556SDmitry Torokhov mod_timer(&bdata->release_timer, 4678ed92556SDmitry Torokhov jiffies + msecs_to_jiffies(bdata->release_delay)); 468d8ee4a1cSLaxman Dewangan out: 469d8ee4a1cSLaxman Dewangan spin_unlock_irqrestore(&bdata->lock, flags); 470d8ee4a1cSLaxman Dewangan return IRQ_HANDLED; 471d8ee4a1cSLaxman Dewangan } 472d8ee4a1cSLaxman Dewangan 47327245519SAlexander Shiyan static void gpio_keys_quiesce_key(void *data) 47427245519SAlexander Shiyan { 47527245519SAlexander Shiyan struct gpio_button_data *bdata = data; 47627245519SAlexander Shiyan 4775feeca3cSGeert Uytterhoeven if (bdata->gpiod) 4788ed92556SDmitry Torokhov cancel_delayed_work_sync(&bdata->work); 4798ed92556SDmitry Torokhov else 4808ed92556SDmitry Torokhov del_timer_sync(&bdata->release_timer); 48127245519SAlexander Shiyan } 48227245519SAlexander Shiyan 4835298cc4cSBill Pemberton static int gpio_keys_setup_key(struct platform_device *pdev, 484d9080921SDmitry Torokhov struct input_dev *input, 48583e4947aSHans de Goede struct gpio_keys_drvdata *ddata, 486700a38b2SDmitry Torokhov const struct gpio_keys_button *button, 48783e4947aSHans de Goede int idx, 488700a38b2SDmitry Torokhov struct fwnode_handle *child) 489bc8f1eafSBen Dooks { 49092a47674SAlexander Stein const char *desc = button->desc ? button->desc : "gpio_keys"; 4919e3af04fSMika Westerberg struct device *dev = &pdev->dev; 49283e4947aSHans de Goede struct gpio_button_data *bdata = &ddata->data[idx]; 493d8ee4a1cSLaxman Dewangan irq_handler_t isr; 4949e3af04fSMika Westerberg unsigned long irqflags; 49527245519SAlexander Shiyan int irq; 49627245519SAlexander Shiyan int error; 497bc8f1eafSBen Dooks 498d9080921SDmitry Torokhov bdata->input = input; 499d9080921SDmitry Torokhov bdata->button = button; 500d8ee4a1cSLaxman Dewangan spin_lock_init(&bdata->lock); 501d8ee4a1cSLaxman Dewangan 502700a38b2SDmitry Torokhov if (child) { 5034b094797SBoris Brezillon bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, 5044b094797SBoris Brezillon child, 5054b094797SBoris Brezillon GPIOD_IN, 5064b094797SBoris Brezillon desc); 507700a38b2SDmitry Torokhov if (IS_ERR(bdata->gpiod)) { 508700a38b2SDmitry Torokhov error = PTR_ERR(bdata->gpiod); 509700a38b2SDmitry Torokhov if (error == -ENOENT) { 510700a38b2SDmitry Torokhov /* 511700a38b2SDmitry Torokhov * GPIO is optional, we may be dealing with 512700a38b2SDmitry Torokhov * purely interrupt-driven setup. 513700a38b2SDmitry Torokhov */ 514700a38b2SDmitry Torokhov bdata->gpiod = NULL; 515700a38b2SDmitry Torokhov } else { 516700a38b2SDmitry Torokhov if (error != -EPROBE_DEFER) 517700a38b2SDmitry Torokhov dev_err(dev, "failed to get gpio: %d\n", 518700a38b2SDmitry Torokhov error); 519700a38b2SDmitry Torokhov return error; 520700a38b2SDmitry Torokhov } 521700a38b2SDmitry Torokhov } 522700a38b2SDmitry Torokhov } else if (gpio_is_valid(button->gpio)) { 5235feeca3cSGeert Uytterhoeven /* 5245feeca3cSGeert Uytterhoeven * Legacy GPIO number, so request the GPIO here and 5255feeca3cSGeert Uytterhoeven * convert it to descriptor. 5265feeca3cSGeert Uytterhoeven */ 5275feeca3cSGeert Uytterhoeven unsigned flags = GPIOF_IN; 528bc8f1eafSBen Dooks 5295feeca3cSGeert Uytterhoeven if (button->active_low) 5305feeca3cSGeert Uytterhoeven flags |= GPIOF_ACTIVE_LOW; 5315feeca3cSGeert Uytterhoeven 532b4e66e7dSGuenter Roeck error = devm_gpio_request_one(dev, button->gpio, flags, desc); 533bc8f1eafSBen Dooks if (error < 0) { 534d8ee4a1cSLaxman Dewangan dev_err(dev, "Failed to request GPIO %d, error %d\n", 535bc8f1eafSBen Dooks button->gpio, error); 536d8ee4a1cSLaxman Dewangan return error; 537bc8f1eafSBen Dooks } 538bc8f1eafSBen Dooks 5395feeca3cSGeert Uytterhoeven bdata->gpiod = gpio_to_desc(button->gpio); 5405feeca3cSGeert Uytterhoeven if (!bdata->gpiod) 5415feeca3cSGeert Uytterhoeven return -EINVAL; 542700a38b2SDmitry Torokhov } 5435feeca3cSGeert Uytterhoeven 544700a38b2SDmitry Torokhov if (bdata->gpiod) { 545*83fc580dSJeffy Chen bool active_low = gpiod_is_active_low(bdata->gpiod); 546*83fc580dSJeffy Chen 54728ed684fSGrazvydas Ignotas if (button->debounce_interval) { 5485feeca3cSGeert Uytterhoeven error = gpiod_set_debounce(bdata->gpiod, 54928ed684fSGrazvydas Ignotas button->debounce_interval * 1000); 55028ed684fSGrazvydas Ignotas /* use timer if gpiolib doesn't provide debounce */ 55128ed684fSGrazvydas Ignotas if (error < 0) 5528ed92556SDmitry Torokhov bdata->software_debounce = 553d8ee4a1cSLaxman Dewangan button->debounce_interval; 55428ed684fSGrazvydas Ignotas } 55528ed684fSGrazvydas Ignotas 55697d86e07SDmitry Torokhov if (button->irq) { 55797d86e07SDmitry Torokhov bdata->irq = button->irq; 55897d86e07SDmitry Torokhov } else { 5595feeca3cSGeert Uytterhoeven irq = gpiod_to_irq(bdata->gpiod); 560bc8f1eafSBen Dooks if (irq < 0) { 561bc8f1eafSBen Dooks error = irq; 562d8ee4a1cSLaxman Dewangan dev_err(dev, 563d8ee4a1cSLaxman Dewangan "Unable to get irq number for GPIO %d, error %d\n", 564bc8f1eafSBen Dooks button->gpio, error); 56527245519SAlexander Shiyan return error; 566d8ee4a1cSLaxman Dewangan } 567d8ee4a1cSLaxman Dewangan bdata->irq = irq; 56897d86e07SDmitry Torokhov } 569d8ee4a1cSLaxman Dewangan 5708ed92556SDmitry Torokhov INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); 571d8ee4a1cSLaxman Dewangan 572d8ee4a1cSLaxman Dewangan isr = gpio_keys_gpio_isr; 573d8ee4a1cSLaxman Dewangan irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; 574d8ee4a1cSLaxman Dewangan 575*83fc580dSJeffy Chen switch (button->wakeup_event_action) { 576*83fc580dSJeffy Chen case EV_ACT_ASSERTED: 577*83fc580dSJeffy Chen bdata->wakeup_trigger_type = active_low ? 578*83fc580dSJeffy Chen IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING; 579*83fc580dSJeffy Chen break; 580*83fc580dSJeffy Chen case EV_ACT_DEASSERTED: 581*83fc580dSJeffy Chen bdata->wakeup_trigger_type = active_low ? 582*83fc580dSJeffy Chen IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING; 583*83fc580dSJeffy Chen break; 584*83fc580dSJeffy Chen case EV_ACT_ANY: 585*83fc580dSJeffy Chen /* fall through */ 586*83fc580dSJeffy Chen default: 587*83fc580dSJeffy Chen /* 588*83fc580dSJeffy Chen * For other cases, we are OK letting suspend/resume 589*83fc580dSJeffy Chen * not reconfigure the trigger type. 590*83fc580dSJeffy Chen */ 591*83fc580dSJeffy Chen break; 592*83fc580dSJeffy Chen } 593d8ee4a1cSLaxman Dewangan } else { 594d8ee4a1cSLaxman Dewangan if (!button->irq) { 595700a38b2SDmitry Torokhov dev_err(dev, "Found button without gpio or irq\n"); 596d8ee4a1cSLaxman Dewangan return -EINVAL; 597d8ee4a1cSLaxman Dewangan } 598700a38b2SDmitry Torokhov 599d8ee4a1cSLaxman Dewangan bdata->irq = button->irq; 600d8ee4a1cSLaxman Dewangan 601d8ee4a1cSLaxman Dewangan if (button->type && button->type != EV_KEY) { 602d8ee4a1cSLaxman Dewangan dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); 603d8ee4a1cSLaxman Dewangan return -EINVAL; 604bc8f1eafSBen Dooks } 605bc8f1eafSBen Dooks 6068ed92556SDmitry Torokhov bdata->release_delay = button->debounce_interval; 60782565a12Sstephen lu timer_setup(&bdata->release_timer, gpio_keys_irq_timer, 0); 608d8ee4a1cSLaxman Dewangan 609d8ee4a1cSLaxman Dewangan isr = gpio_keys_irq_isr; 610d8ee4a1cSLaxman Dewangan irqflags = 0; 611*83fc580dSJeffy Chen 612*83fc580dSJeffy Chen /* 613*83fc580dSJeffy Chen * For IRQ buttons, there is no interrupt for release. 614*83fc580dSJeffy Chen * So we don't need to reconfigure the trigger type for wakeup. 615*83fc580dSJeffy Chen */ 616d8ee4a1cSLaxman Dewangan } 617d8ee4a1cSLaxman Dewangan 61883e4947aSHans de Goede bdata->code = &ddata->keymap[idx]; 61983e4947aSHans de Goede *bdata->code = button->code; 62083e4947aSHans de Goede input_set_capability(input, button->type ?: EV_KEY, *bdata->code); 621d8ee4a1cSLaxman Dewangan 6229e3af04fSMika Westerberg /* 6238ed92556SDmitry Torokhov * Install custom action to cancel release timer and 62427245519SAlexander Shiyan * workqueue item. 62527245519SAlexander Shiyan */ 626b4e66e7dSGuenter Roeck error = devm_add_action(dev, gpio_keys_quiesce_key, bdata); 62727245519SAlexander Shiyan if (error) { 628b4e66e7dSGuenter Roeck dev_err(dev, "failed to register quiesce action, error: %d\n", 62927245519SAlexander Shiyan error); 63027245519SAlexander Shiyan return error; 63127245519SAlexander Shiyan } 63227245519SAlexander Shiyan 63327245519SAlexander Shiyan /* 6349e3af04fSMika Westerberg * If platform has specified that the button can be disabled, 6359e3af04fSMika Westerberg * we don't want it to share the interrupt line. 6369e3af04fSMika Westerberg */ 6379e3af04fSMika Westerberg if (!button->can_disable) 6389e3af04fSMika Westerberg irqflags |= IRQF_SHARED; 6399e3af04fSMika Westerberg 640b4e66e7dSGuenter Roeck error = devm_request_any_context_irq(dev, bdata->irq, isr, irqflags, 641b4e66e7dSGuenter Roeck desc, bdata); 64294a8cab8SPhilippe Langlais if (error < 0) { 643bc8f1eafSBen Dooks dev_err(dev, "Unable to claim irq %d; error %d\n", 644d8ee4a1cSLaxman Dewangan bdata->irq, error); 64527245519SAlexander Shiyan return error; 646bc8f1eafSBen Dooks } 647bc8f1eafSBen Dooks 648bc8f1eafSBen Dooks return 0; 649bc8f1eafSBen Dooks } 650bc8f1eafSBen Dooks 6515b76d7b4SDmitry Torokhov static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) 6525b76d7b4SDmitry Torokhov { 6535b76d7b4SDmitry Torokhov struct input_dev *input = ddata->input; 6545b76d7b4SDmitry Torokhov int i; 6555b76d7b4SDmitry Torokhov 6565b76d7b4SDmitry Torokhov for (i = 0; i < ddata->pdata->nbuttons; i++) { 6575b76d7b4SDmitry Torokhov struct gpio_button_data *bdata = &ddata->data[i]; 6585feeca3cSGeert Uytterhoeven if (bdata->gpiod) 6595b76d7b4SDmitry Torokhov gpio_keys_gpio_report_event(bdata); 6605b76d7b4SDmitry Torokhov } 6615b76d7b4SDmitry Torokhov input_sync(input); 6625b76d7b4SDmitry Torokhov } 6635b76d7b4SDmitry Torokhov 664173bdd74SShubhrajyoti D static int gpio_keys_open(struct input_dev *input) 665173bdd74SShubhrajyoti D { 666173bdd74SShubhrajyoti D struct gpio_keys_drvdata *ddata = input_get_drvdata(input); 667219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = ddata->pdata; 6685b76d7b4SDmitry Torokhov int error; 669173bdd74SShubhrajyoti D 6705b76d7b4SDmitry Torokhov if (pdata->enable) { 6715b76d7b4SDmitry Torokhov error = pdata->enable(input->dev.parent); 6725b76d7b4SDmitry Torokhov if (error) 6735b76d7b4SDmitry Torokhov return error; 6745b76d7b4SDmitry Torokhov } 6755b76d7b4SDmitry Torokhov 6765b76d7b4SDmitry Torokhov /* Report current state of buttons that are connected to GPIOs */ 6775b76d7b4SDmitry Torokhov gpio_keys_report_state(ddata); 6785b76d7b4SDmitry Torokhov 6795b76d7b4SDmitry Torokhov return 0; 680173bdd74SShubhrajyoti D } 681173bdd74SShubhrajyoti D 682173bdd74SShubhrajyoti D static void gpio_keys_close(struct input_dev *input) 683173bdd74SShubhrajyoti D { 684173bdd74SShubhrajyoti D struct gpio_keys_drvdata *ddata = input_get_drvdata(input); 685219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = ddata->pdata; 686173bdd74SShubhrajyoti D 687219edc71SAlexandre Pereira da Silva if (pdata->disable) 688219edc71SAlexandre Pereira da Silva pdata->disable(input->dev.parent); 689173bdd74SShubhrajyoti D } 690173bdd74SShubhrajyoti D 691fd05d089SDavid Jander /* 692fd05d089SDavid Jander * Handlers for alternative sources of platform_data 693fd05d089SDavid Jander */ 694219edc71SAlexandre Pereira da Silva 695fd05d089SDavid Jander /* 696700a38b2SDmitry Torokhov * Translate properties into platform_data 697fd05d089SDavid Jander */ 6985298cc4cSBill Pemberton static struct gpio_keys_platform_data * 699219edc71SAlexandre Pereira da Silva gpio_keys_get_devtree_pdata(struct device *dev) 700fd05d089SDavid Jander { 701219edc71SAlexandre Pereira da Silva struct gpio_keys_platform_data *pdata; 702219edc71SAlexandre Pereira da Silva struct gpio_keys_button *button; 703700a38b2SDmitry Torokhov struct fwnode_handle *child; 704219edc71SAlexandre Pereira da Silva int nbuttons; 705fd05d089SDavid Jander 706700a38b2SDmitry Torokhov nbuttons = device_get_child_node_count(dev); 7075d422f2eSAndy Shevchenko if (nbuttons == 0) 7085d422f2eSAndy Shevchenko return ERR_PTR(-ENODEV); 709219edc71SAlexandre Pereira da Silva 7105d422f2eSAndy Shevchenko pdata = devm_kzalloc(dev, 7115d422f2eSAndy Shevchenko sizeof(*pdata) + nbuttons * sizeof(*button), 712219edc71SAlexandre Pereira da Silva GFP_KERNEL); 7135d422f2eSAndy Shevchenko if (!pdata) 7145d422f2eSAndy Shevchenko return ERR_PTR(-ENOMEM); 715219edc71SAlexandre Pereira da Silva 7160f78ba96SDmitry Torokhov button = (struct gpio_keys_button *)(pdata + 1); 7170f78ba96SDmitry Torokhov 7180f78ba96SDmitry Torokhov pdata->buttons = button; 719219edc71SAlexandre Pereira da Silva pdata->nbuttons = nbuttons; 720fd05d089SDavid Jander 721700a38b2SDmitry Torokhov pdata->rep = device_property_read_bool(dev, "autorepeat"); 722fd05d089SDavid Jander 723700a38b2SDmitry Torokhov device_property_read_string(dev, "label", &pdata->name); 724c4dc5f8cSLaxman Dewangan 725700a38b2SDmitry Torokhov device_for_each_child_node(dev, child) { 726700a38b2SDmitry Torokhov if (is_of_node(child)) 727700a38b2SDmitry Torokhov button->irq = 728700a38b2SDmitry Torokhov irq_of_parse_and_map(to_of_node(child), 0); 729fd05d089SDavid Jander 730700a38b2SDmitry Torokhov if (fwnode_property_read_u32(child, "linux,code", 731700a38b2SDmitry Torokhov &button->code)) { 732700a38b2SDmitry Torokhov dev_err(dev, "Button without keycode\n"); 733700a38b2SDmitry Torokhov fwnode_handle_put(child); 73497d86e07SDmitry Torokhov return ERR_PTR(-EINVAL); 73597d86e07SDmitry Torokhov } 736fd05d089SDavid Jander 737700a38b2SDmitry Torokhov fwnode_property_read_string(child, "label", &button->desc); 738fd05d089SDavid Jander 739700a38b2SDmitry Torokhov if (fwnode_property_read_u32(child, "linux,input-type", 740700a38b2SDmitry Torokhov &button->type)) 741219edc71SAlexandre Pereira da Silva button->type = EV_KEY; 742fd05d089SDavid Jander 743700a38b2SDmitry Torokhov button->wakeup = 744700a38b2SDmitry Torokhov fwnode_property_read_bool(child, "wakeup-source") || 74599b4ffbdSDmitry Torokhov /* legacy name */ 746700a38b2SDmitry Torokhov fwnode_property_read_bool(child, "gpio-key,wakeup"); 747219edc71SAlexandre Pereira da Silva 748*83fc580dSJeffy Chen fwnode_property_read_u32(child, "wakeup-event-action", 749*83fc580dSJeffy Chen &button->wakeup_event_action); 750*83fc580dSJeffy Chen 751700a38b2SDmitry Torokhov button->can_disable = 752700a38b2SDmitry Torokhov fwnode_property_read_bool(child, "linux,can-disable"); 75397d86e07SDmitry Torokhov 754700a38b2SDmitry Torokhov if (fwnode_property_read_u32(child, "debounce-interval", 755219edc71SAlexandre Pereira da Silva &button->debounce_interval)) 756219edc71SAlexandre Pereira da Silva button->debounce_interval = 5; 7570f78ba96SDmitry Torokhov 7580f78ba96SDmitry Torokhov button++; 759219edc71SAlexandre Pereira da Silva } 760219edc71SAlexandre Pereira da Silva 761219edc71SAlexandre Pereira da Silva return pdata; 762fd05d089SDavid Jander } 763fd05d089SDavid Jander 76422daae31SJingoo Han static const struct of_device_id gpio_keys_of_match[] = { 765fd05d089SDavid Jander { .compatible = "gpio-keys", }, 766fd05d089SDavid Jander { }, 767fd05d089SDavid Jander }; 768fd05d089SDavid Jander MODULE_DEVICE_TABLE(of, gpio_keys_of_match); 769fd05d089SDavid Jander 7705298cc4cSBill Pemberton static int gpio_keys_probe(struct platform_device *pdev) 77178a56aabSPhil Blundell { 772db19fd8bSBen Dooks struct device *dev = &pdev->dev; 773219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); 774700a38b2SDmitry Torokhov struct fwnode_handle *child = NULL; 775219edc71SAlexandre Pereira da Silva struct gpio_keys_drvdata *ddata; 77678a56aabSPhil Blundell struct input_dev *input; 7775d422f2eSAndy Shevchenko size_t size; 77878a56aabSPhil Blundell int i, error; 779e15b0213SAnti Sullin int wakeup = 0; 78078a56aabSPhil Blundell 781fd05d089SDavid Jander if (!pdata) { 782219edc71SAlexandre Pereira da Silva pdata = gpio_keys_get_devtree_pdata(dev); 783219edc71SAlexandre Pereira da Silva if (IS_ERR(pdata)) 784219edc71SAlexandre Pereira da Silva return PTR_ERR(pdata); 785fd05d089SDavid Jander } 786fd05d089SDavid Jander 7875d422f2eSAndy Shevchenko size = sizeof(struct gpio_keys_drvdata) + 7885d422f2eSAndy Shevchenko pdata->nbuttons * sizeof(struct gpio_button_data); 7895d422f2eSAndy Shevchenko ddata = devm_kzalloc(dev, size, GFP_KERNEL); 7905d422f2eSAndy Shevchenko if (!ddata) { 791db19fd8bSBen Dooks dev_err(dev, "failed to allocate state\n"); 7925d422f2eSAndy Shevchenko return -ENOMEM; 7935d422f2eSAndy Shevchenko } 7945d422f2eSAndy Shevchenko 79583e4947aSHans de Goede ddata->keymap = devm_kcalloc(dev, 79683e4947aSHans de Goede pdata->nbuttons, sizeof(ddata->keymap[0]), 79783e4947aSHans de Goede GFP_KERNEL); 79883e4947aSHans de Goede if (!ddata->keymap) 79983e4947aSHans de Goede return -ENOMEM; 80083e4947aSHans de Goede 8015d422f2eSAndy Shevchenko input = devm_input_allocate_device(dev); 8025d422f2eSAndy Shevchenko if (!input) { 8035d422f2eSAndy Shevchenko dev_err(dev, "failed to allocate input device\n"); 8045d422f2eSAndy Shevchenko return -ENOMEM; 805a33466e3SDmitry Baryshkov } 80678a56aabSPhil Blundell 807219edc71SAlexandre Pereira da Silva ddata->pdata = pdata; 8089e3af04fSMika Westerberg ddata->input = input; 8099e3af04fSMika Westerberg mutex_init(&ddata->disable_lock); 8109e3af04fSMika Westerberg 811a33466e3SDmitry Baryshkov platform_set_drvdata(pdev, ddata); 812173bdd74SShubhrajyoti D input_set_drvdata(input, ddata); 81378a56aabSPhil Blundell 81446711277SAlexander Stein input->name = pdata->name ? : pdev->name; 81578a56aabSPhil Blundell input->phys = "gpio-keys/input0"; 816b4e66e7dSGuenter Roeck input->dev.parent = dev; 817173bdd74SShubhrajyoti D input->open = gpio_keys_open; 818173bdd74SShubhrajyoti D input->close = gpio_keys_close; 81978a56aabSPhil Blundell 82078a56aabSPhil Blundell input->id.bustype = BUS_HOST; 82178a56aabSPhil Blundell input->id.vendor = 0x0001; 82278a56aabSPhil Blundell input->id.product = 0x0001; 82378a56aabSPhil Blundell input->id.version = 0x0100; 82478a56aabSPhil Blundell 82583e4947aSHans de Goede input->keycode = ddata->keymap; 82683e4947aSHans de Goede input->keycodesize = sizeof(ddata->keymap[0]); 82783e4947aSHans de Goede input->keycodemax = pdata->nbuttons; 82883e4947aSHans de Goede 829b67b4b11SDominic Curran /* Enable auto repeat feature of Linux input subsystem */ 830b67b4b11SDominic Curran if (pdata->rep) 831b67b4b11SDominic Curran __set_bit(EV_REP, input->evbit); 832b67b4b11SDominic Curran 83378a56aabSPhil Blundell for (i = 0; i < pdata->nbuttons; i++) { 834d9080921SDmitry Torokhov const struct gpio_keys_button *button = &pdata->buttons[i]; 83578a56aabSPhil Blundell 836700a38b2SDmitry Torokhov if (!dev_get_platdata(dev)) { 837b4e66e7dSGuenter Roeck child = device_get_next_child_node(dev, child); 838700a38b2SDmitry Torokhov if (!child) { 839b4e66e7dSGuenter Roeck dev_err(dev, 840700a38b2SDmitry Torokhov "missing child device node for entry %d\n", 841700a38b2SDmitry Torokhov i); 842700a38b2SDmitry Torokhov return -EINVAL; 843700a38b2SDmitry Torokhov } 844700a38b2SDmitry Torokhov } 845700a38b2SDmitry Torokhov 84683e4947aSHans de Goede error = gpio_keys_setup_key(pdev, input, ddata, 84783e4947aSHans de Goede button, i, child); 848700a38b2SDmitry Torokhov if (error) { 849700a38b2SDmitry Torokhov fwnode_handle_put(child); 85027245519SAlexander Shiyan return error; 851700a38b2SDmitry Torokhov } 85284767d00SRoman Moravcik 853e15b0213SAnti Sullin if (button->wakeup) 854e15b0213SAnti Sullin wakeup = 1; 85578a56aabSPhil Blundell } 85678a56aabSPhil Blundell 857700a38b2SDmitry Torokhov fwnode_handle_put(child); 858700a38b2SDmitry Torokhov 8593184125eSDmitry Torokhov error = devm_device_add_group(dev, &gpio_keys_attr_group); 8609e3af04fSMika Westerberg if (error) { 8619e3af04fSMika Westerberg dev_err(dev, "Unable to export keys/switches, error: %d\n", 8629e3af04fSMika Westerberg error); 86327245519SAlexander Shiyan return error; 8649e3af04fSMika Westerberg } 8659e3af04fSMika Westerberg 86678a56aabSPhil Blundell error = input_register_device(input); 86778a56aabSPhil Blundell if (error) { 8689e3af04fSMika Westerberg dev_err(dev, "Unable to register input device, error: %d\n", 8699e3af04fSMika Westerberg error); 87078a56aabSPhil Blundell return error; 87178a56aabSPhil Blundell } 87278a56aabSPhil Blundell 8733184125eSDmitry Torokhov device_init_wakeup(dev, wakeup); 8749e3af04fSMika Westerberg 87578a56aabSPhil Blundell return 0; 87678a56aabSPhil Blundell } 87778a56aabSPhil Blundell 878*83fc580dSJeffy Chen static int __maybe_unused 879*83fc580dSJeffy Chen gpio_keys_button_enable_wakeup(struct gpio_button_data *bdata) 880*83fc580dSJeffy Chen { 881*83fc580dSJeffy Chen int error; 882*83fc580dSJeffy Chen 883*83fc580dSJeffy Chen error = enable_irq_wake(bdata->irq); 884*83fc580dSJeffy Chen if (error) { 885*83fc580dSJeffy Chen dev_err(bdata->input->dev.parent, 886*83fc580dSJeffy Chen "failed to configure IRQ %d as wakeup source: %d\n", 887*83fc580dSJeffy Chen bdata->irq, error); 888*83fc580dSJeffy Chen return error; 889*83fc580dSJeffy Chen } 890*83fc580dSJeffy Chen 891*83fc580dSJeffy Chen if (bdata->wakeup_trigger_type) { 892*83fc580dSJeffy Chen error = irq_set_irq_type(bdata->irq, 893*83fc580dSJeffy Chen bdata->wakeup_trigger_type); 894*83fc580dSJeffy Chen if (error) { 895*83fc580dSJeffy Chen dev_err(bdata->input->dev.parent, 896*83fc580dSJeffy Chen "failed to set wakeup trigger %08x for IRQ %d: %d\n", 897*83fc580dSJeffy Chen bdata->wakeup_trigger_type, bdata->irq, error); 898*83fc580dSJeffy Chen disable_irq_wake(bdata->irq); 899*83fc580dSJeffy Chen return error; 900*83fc580dSJeffy Chen } 901*83fc580dSJeffy Chen } 902*83fc580dSJeffy Chen 903*83fc580dSJeffy Chen return 0; 904*83fc580dSJeffy Chen } 905*83fc580dSJeffy Chen 906*83fc580dSJeffy Chen static void __maybe_unused 907*83fc580dSJeffy Chen gpio_keys_button_disable_wakeup(struct gpio_button_data *bdata) 908*83fc580dSJeffy Chen { 909*83fc580dSJeffy Chen int error; 910*83fc580dSJeffy Chen 911*83fc580dSJeffy Chen /* 912*83fc580dSJeffy Chen * The trigger type is always both edges for gpio-based keys and we do 913*83fc580dSJeffy Chen * not support changing wakeup trigger for interrupt-based keys. 914*83fc580dSJeffy Chen */ 915*83fc580dSJeffy Chen if (bdata->wakeup_trigger_type) { 916*83fc580dSJeffy Chen error = irq_set_irq_type(bdata->irq, IRQ_TYPE_EDGE_BOTH); 917*83fc580dSJeffy Chen if (error) 918*83fc580dSJeffy Chen dev_warn(bdata->input->dev.parent, 919*83fc580dSJeffy Chen "failed to restore interrupt trigger for IRQ %d: %d\n", 920*83fc580dSJeffy Chen bdata->irq, error); 921*83fc580dSJeffy Chen } 922*83fc580dSJeffy Chen 923*83fc580dSJeffy Chen error = disable_irq_wake(bdata->irq); 924*83fc580dSJeffy Chen if (error) 925*83fc580dSJeffy Chen dev_warn(bdata->input->dev.parent, 926*83fc580dSJeffy Chen "failed to disable IRQ %d as wake source: %d\n", 927*83fc580dSJeffy Chen bdata->irq, error); 928*83fc580dSJeffy Chen } 929*83fc580dSJeffy Chen 930*83fc580dSJeffy Chen static int __maybe_unused 931*83fc580dSJeffy Chen gpio_keys_enable_wakeup(struct gpio_keys_drvdata *ddata) 932*83fc580dSJeffy Chen { 933*83fc580dSJeffy Chen struct gpio_button_data *bdata; 934*83fc580dSJeffy Chen int error; 935*83fc580dSJeffy Chen int i; 936*83fc580dSJeffy Chen 937*83fc580dSJeffy Chen for (i = 0; i < ddata->pdata->nbuttons; i++) { 938*83fc580dSJeffy Chen bdata = &ddata->data[i]; 939*83fc580dSJeffy Chen if (bdata->button->wakeup) { 940*83fc580dSJeffy Chen error = gpio_keys_button_enable_wakeup(bdata); 941*83fc580dSJeffy Chen if (error) 942*83fc580dSJeffy Chen goto err_out; 943*83fc580dSJeffy Chen } 944*83fc580dSJeffy Chen bdata->suspended = true; 945*83fc580dSJeffy Chen } 946*83fc580dSJeffy Chen 947*83fc580dSJeffy Chen return 0; 948*83fc580dSJeffy Chen 949*83fc580dSJeffy Chen err_out: 950*83fc580dSJeffy Chen while (i--) { 951*83fc580dSJeffy Chen bdata = &ddata->data[i]; 952*83fc580dSJeffy Chen if (bdata->button->wakeup) 953*83fc580dSJeffy Chen gpio_keys_button_disable_wakeup(bdata); 954*83fc580dSJeffy Chen bdata->suspended = false; 955*83fc580dSJeffy Chen } 956*83fc580dSJeffy Chen 957*83fc580dSJeffy Chen return error; 958*83fc580dSJeffy Chen } 959*83fc580dSJeffy Chen 960*83fc580dSJeffy Chen static void __maybe_unused 961*83fc580dSJeffy Chen gpio_keys_disable_wakeup(struct gpio_keys_drvdata *ddata) 962*83fc580dSJeffy Chen { 963*83fc580dSJeffy Chen struct gpio_button_data *bdata; 964*83fc580dSJeffy Chen int i; 965*83fc580dSJeffy Chen 966*83fc580dSJeffy Chen for (i = 0; i < ddata->pdata->nbuttons; i++) { 967*83fc580dSJeffy Chen bdata = &ddata->data[i]; 968*83fc580dSJeffy Chen bdata->suspended = false; 969*83fc580dSJeffy Chen if (irqd_is_wakeup_set(irq_get_irq_data(bdata->irq))) 970*83fc580dSJeffy Chen gpio_keys_button_disable_wakeup(bdata); 971*83fc580dSJeffy Chen } 972*83fc580dSJeffy Chen } 973*83fc580dSJeffy Chen 974f9645f22SDmitry Torokhov static int __maybe_unused gpio_keys_suspend(struct device *dev) 975e15b0213SAnti Sullin { 976fd05d089SDavid Jander struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 977dda19a92SJonas Aaberg struct input_dev *input = ddata->input; 978*83fc580dSJeffy Chen int error; 979e15b0213SAnti Sullin 980fd05d089SDavid Jander if (device_may_wakeup(dev)) { 981*83fc580dSJeffy Chen error = gpio_keys_enable_wakeup(ddata); 982*83fc580dSJeffy Chen if (error) 983*83fc580dSJeffy Chen return error; 984dda19a92SJonas Aaberg } else { 985dda19a92SJonas Aaberg mutex_lock(&input->mutex); 986dda19a92SJonas Aaberg if (input->users) 987dda19a92SJonas Aaberg gpio_keys_close(input); 988dda19a92SJonas Aaberg mutex_unlock(&input->mutex); 989e15b0213SAnti Sullin } 990e15b0213SAnti Sullin 991e15b0213SAnti Sullin return 0; 992e15b0213SAnti Sullin } 993e15b0213SAnti Sullin 994f9645f22SDmitry Torokhov static int __maybe_unused gpio_keys_resume(struct device *dev) 995e15b0213SAnti Sullin { 996fd05d089SDavid Jander struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 997dda19a92SJonas Aaberg struct input_dev *input = ddata->input; 998dda19a92SJonas Aaberg int error = 0; 999e15b0213SAnti Sullin 1000dda19a92SJonas Aaberg if (device_may_wakeup(dev)) { 1001*83fc580dSJeffy Chen gpio_keys_disable_wakeup(ddata); 1002dda19a92SJonas Aaberg } else { 1003dda19a92SJonas Aaberg mutex_lock(&input->mutex); 1004dda19a92SJonas Aaberg if (input->users) 1005dda19a92SJonas Aaberg error = gpio_keys_open(input); 1006dda19a92SJonas Aaberg mutex_unlock(&input->mutex); 1007dda19a92SJonas Aaberg } 1008dda19a92SJonas Aaberg 1009dda19a92SJonas Aaberg if (error) 1010dda19a92SJonas Aaberg return error; 10115b76d7b4SDmitry Torokhov 10125b76d7b4SDmitry Torokhov gpio_keys_report_state(ddata); 1013e15b0213SAnti Sullin return 0; 1014e15b0213SAnti Sullin } 1015e15b0213SAnti Sullin 1016bdda8216SDmitry Torokhov static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); 1017bdda8216SDmitry Torokhov 10189b07044cSUwe Kleine-König static struct platform_driver gpio_keys_device_driver = { 101978a56aabSPhil Blundell .probe = gpio_keys_probe, 102078a56aabSPhil Blundell .driver = { 102178a56aabSPhil Blundell .name = "gpio-keys", 1022ae78e0e0SMike Rapoport .pm = &gpio_keys_pm_ops, 1023700a38b2SDmitry Torokhov .of_match_table = gpio_keys_of_match, 102478a56aabSPhil Blundell } 102578a56aabSPhil Blundell }; 102678a56aabSPhil Blundell 102778a56aabSPhil Blundell static int __init gpio_keys_init(void) 102878a56aabSPhil Blundell { 102978a56aabSPhil Blundell return platform_driver_register(&gpio_keys_device_driver); 103078a56aabSPhil Blundell } 103178a56aabSPhil Blundell 103278a56aabSPhil Blundell static void __exit gpio_keys_exit(void) 103378a56aabSPhil Blundell { 103478a56aabSPhil Blundell platform_driver_unregister(&gpio_keys_device_driver); 103578a56aabSPhil Blundell } 103678a56aabSPhil Blundell 1037b2330205SDavid Jander late_initcall(gpio_keys_init); 103878a56aabSPhil Blundell module_exit(gpio_keys_exit); 103978a56aabSPhil Blundell 104078a56aabSPhil Blundell MODULE_LICENSE("GPL"); 104178a56aabSPhil Blundell MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); 10427e2ecdf4SDavid Jander MODULE_DESCRIPTION("Keyboard driver for GPIOs"); 1043d7b5247bSKay Sievers MODULE_ALIAS("platform:gpio-keys"); 1044