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> 29415a4caaSSachin Kamat #include <linux/of.h> 30fd05d089SDavid Jander #include <linux/of_platform.h> 31fd05d089SDavid Jander #include <linux/of_gpio.h> 32f2d347ffSAlexander Stein #include <linux/of_irq.h> 33d8ee4a1cSLaxman Dewangan #include <linux/spinlock.h> 3478a56aabSPhil Blundell 35a33466e3SDmitry Baryshkov struct gpio_button_data { 36d9080921SDmitry Torokhov const struct gpio_keys_button *button; 37a33466e3SDmitry Baryshkov struct input_dev *input; 388ed92556SDmitry Torokhov 398ed92556SDmitry Torokhov struct timer_list release_timer; 408ed92556SDmitry Torokhov unsigned int release_delay; /* in msecs, for IRQ-only buttons */ 418ed92556SDmitry Torokhov 428ed92556SDmitry Torokhov struct delayed_work work; 438ed92556SDmitry Torokhov unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */ 448ed92556SDmitry Torokhov 45d8ee4a1cSLaxman Dewangan unsigned int irq; 46d8ee4a1cSLaxman Dewangan spinlock_t lock; 479e3af04fSMika Westerberg bool disabled; 48d8ee4a1cSLaxman Dewangan bool key_pressed; 49a33466e3SDmitry Baryshkov }; 50a33466e3SDmitry Baryshkov 51a33466e3SDmitry Baryshkov struct gpio_keys_drvdata { 52219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata; 53a33466e3SDmitry Baryshkov struct input_dev *input; 549e3af04fSMika Westerberg struct mutex disable_lock; 55a33466e3SDmitry Baryshkov struct gpio_button_data data[0]; 56a33466e3SDmitry Baryshkov }; 57a33466e3SDmitry Baryshkov 589e3af04fSMika Westerberg /* 599e3af04fSMika Westerberg * SYSFS interface for enabling/disabling keys and switches: 609e3af04fSMika Westerberg * 619e3af04fSMika Westerberg * There are 4 attributes under /sys/devices/platform/gpio-keys/ 629e3af04fSMika Westerberg * keys [ro] - bitmap of keys (EV_KEY) which can be 639e3af04fSMika Westerberg * disabled 649e3af04fSMika Westerberg * switches [ro] - bitmap of switches (EV_SW) which can be 659e3af04fSMika Westerberg * disabled 669e3af04fSMika Westerberg * disabled_keys [rw] - bitmap of keys currently disabled 679e3af04fSMika Westerberg * disabled_switches [rw] - bitmap of switches currently disabled 689e3af04fSMika Westerberg * 699e3af04fSMika Westerberg * Userland can change these values and hence disable event generation 709e3af04fSMika Westerberg * for each key (or switch). Disabling a key means its interrupt line 719e3af04fSMika Westerberg * is disabled. 729e3af04fSMika Westerberg * 739e3af04fSMika Westerberg * For example, if we have following switches set up as gpio-keys: 749e3af04fSMika Westerberg * SW_DOCK = 5 759e3af04fSMika Westerberg * SW_CAMERA_LENS_COVER = 9 769e3af04fSMika Westerberg * SW_KEYPAD_SLIDE = 10 779e3af04fSMika Westerberg * SW_FRONT_PROXIMITY = 11 789e3af04fSMika Westerberg * This is read from switches: 799e3af04fSMika Westerberg * 11-9,5 809e3af04fSMika Westerberg * Next we want to disable proximity (11) and dock (5), we write: 819e3af04fSMika Westerberg * 11,5 829e3af04fSMika Westerberg * to file disabled_switches. Now proximity and dock IRQs are disabled. 839e3af04fSMika Westerberg * This can be verified by reading the file disabled_switches: 849e3af04fSMika Westerberg * 11,5 859e3af04fSMika Westerberg * If we now want to enable proximity (11) switch we write: 869e3af04fSMika Westerberg * 5 879e3af04fSMika Westerberg * to disabled_switches. 889e3af04fSMika Westerberg * 899e3af04fSMika Westerberg * We can disable only those keys which don't allow sharing the irq. 909e3af04fSMika Westerberg */ 919e3af04fSMika Westerberg 929e3af04fSMika Westerberg /** 939e3af04fSMika Westerberg * get_n_events_by_type() - returns maximum number of events per @type 949e3af04fSMika Westerberg * @type: type of button (%EV_KEY, %EV_SW) 959e3af04fSMika Westerberg * 969e3af04fSMika Westerberg * Return value of this function can be used to allocate bitmap 979e3af04fSMika Westerberg * large enough to hold all bits for given type. 989e3af04fSMika Westerberg */ 99*8679ee42SDmitry Torokhov static int get_n_events_by_type(int type) 1009e3af04fSMika Westerberg { 1019e3af04fSMika Westerberg BUG_ON(type != EV_SW && type != EV_KEY); 1029e3af04fSMika Westerberg 1039e3af04fSMika Westerberg return (type == EV_KEY) ? KEY_CNT : SW_CNT; 1049e3af04fSMika Westerberg } 1059e3af04fSMika Westerberg 1069e3af04fSMika Westerberg /** 107*8679ee42SDmitry Torokhov * get_bm_events_by_type() - returns bitmap of supported events per @type 108*8679ee42SDmitry Torokhov * @input: input device from which bitmap is retrieved 109*8679ee42SDmitry Torokhov * @type: type of button (%EV_KEY, %EV_SW) 110*8679ee42SDmitry Torokhov * 111*8679ee42SDmitry Torokhov * Return value of this function can be used to allocate bitmap 112*8679ee42SDmitry Torokhov * large enough to hold all bits for given type. 113*8679ee42SDmitry Torokhov */ 114*8679ee42SDmitry Torokhov static const unsigned long *get_bm_events_by_type(struct input_dev *dev, 115*8679ee42SDmitry Torokhov int type) 116*8679ee42SDmitry Torokhov { 117*8679ee42SDmitry Torokhov BUG_ON(type != EV_SW && type != EV_KEY); 118*8679ee42SDmitry Torokhov 119*8679ee42SDmitry Torokhov return (type == EV_KEY) ? dev->keybit : dev->swbit; 120*8679ee42SDmitry Torokhov } 121*8679ee42SDmitry Torokhov 122*8679ee42SDmitry Torokhov /** 1239e3af04fSMika Westerberg * gpio_keys_disable_button() - disables given GPIO button 1249e3af04fSMika Westerberg * @bdata: button data for button to be disabled 1259e3af04fSMika Westerberg * 1269e3af04fSMika Westerberg * Disables button pointed by @bdata. This is done by masking 1279e3af04fSMika Westerberg * IRQ line. After this function is called, button won't generate 1289e3af04fSMika Westerberg * input events anymore. Note that one can only disable buttons 1299e3af04fSMika Westerberg * that don't share IRQs. 1309e3af04fSMika Westerberg * 1319e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1329e3af04fSMika Westerberg * this function to avoid races when concurrent threads are 1339e3af04fSMika Westerberg * disabling buttons at the same time. 1349e3af04fSMika Westerberg */ 1359e3af04fSMika Westerberg static void gpio_keys_disable_button(struct gpio_button_data *bdata) 1369e3af04fSMika Westerberg { 1379e3af04fSMika Westerberg if (!bdata->disabled) { 1389e3af04fSMika Westerberg /* 1398ed92556SDmitry Torokhov * Disable IRQ and associated timer/work structure. 1409e3af04fSMika Westerberg */ 141d8ee4a1cSLaxman Dewangan disable_irq(bdata->irq); 1428ed92556SDmitry Torokhov 1438ed92556SDmitry Torokhov if (gpio_is_valid(bdata->button->gpio)) 1448ed92556SDmitry Torokhov cancel_delayed_work_sync(&bdata->work); 1458ed92556SDmitry Torokhov else 1468ed92556SDmitry Torokhov del_timer_sync(&bdata->release_timer); 1479e3af04fSMika Westerberg 1489e3af04fSMika Westerberg bdata->disabled = true; 1499e3af04fSMika Westerberg } 1509e3af04fSMika Westerberg } 1519e3af04fSMika Westerberg 1529e3af04fSMika Westerberg /** 1539e3af04fSMika Westerberg * gpio_keys_enable_button() - enables given GPIO button 1549e3af04fSMika Westerberg * @bdata: button data for button to be disabled 1559e3af04fSMika Westerberg * 1569e3af04fSMika Westerberg * Enables given button pointed by @bdata. 1579e3af04fSMika Westerberg * 1589e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1599e3af04fSMika Westerberg * this function to avoid races with concurrent threads trying 1609e3af04fSMika Westerberg * to enable the same button at the same time. 1619e3af04fSMika Westerberg */ 1629e3af04fSMika Westerberg static void gpio_keys_enable_button(struct gpio_button_data *bdata) 1639e3af04fSMika Westerberg { 1649e3af04fSMika Westerberg if (bdata->disabled) { 165d8ee4a1cSLaxman Dewangan enable_irq(bdata->irq); 1669e3af04fSMika Westerberg bdata->disabled = false; 1679e3af04fSMika Westerberg } 1689e3af04fSMika Westerberg } 1699e3af04fSMika Westerberg 1709e3af04fSMika Westerberg /** 1719e3af04fSMika Westerberg * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons 1729e3af04fSMika Westerberg * @ddata: pointer to drvdata 1739e3af04fSMika Westerberg * @buf: buffer where stringified bitmap is written 1749e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 1759e3af04fSMika Westerberg * @only_disabled: does caller want only those buttons that are 1769e3af04fSMika Westerberg * currently disabled or all buttons that can be 1779e3af04fSMika Westerberg * disabled 1789e3af04fSMika Westerberg * 1799e3af04fSMika Westerberg * This function writes buttons that can be disabled to @buf. If 1809e3af04fSMika Westerberg * @only_disabled is true, then @buf contains only those buttons 1819e3af04fSMika Westerberg * that are currently disabled. Returns 0 on success or negative 1829e3af04fSMika Westerberg * errno on failure. 1839e3af04fSMika Westerberg */ 1849e3af04fSMika Westerberg static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, 1859e3af04fSMika Westerberg char *buf, unsigned int type, 1869e3af04fSMika Westerberg bool only_disabled) 1879e3af04fSMika Westerberg { 1889e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 1899e3af04fSMika Westerberg unsigned long *bits; 1909e3af04fSMika Westerberg ssize_t ret; 1919e3af04fSMika Westerberg int i; 1929e3af04fSMika Westerberg 1939e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 1949e3af04fSMika Westerberg if (!bits) 1959e3af04fSMika Westerberg return -ENOMEM; 1969e3af04fSMika Westerberg 197219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 1989e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 1999e3af04fSMika Westerberg 2009e3af04fSMika Westerberg if (bdata->button->type != type) 2019e3af04fSMika Westerberg continue; 2029e3af04fSMika Westerberg 2039e3af04fSMika Westerberg if (only_disabled && !bdata->disabled) 2049e3af04fSMika Westerberg continue; 2059e3af04fSMika Westerberg 2069e3af04fSMika Westerberg __set_bit(bdata->button->code, bits); 2079e3af04fSMika Westerberg } 2089e3af04fSMika Westerberg 2090b480037STejun Heo ret = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", n_events, bits); 2109e3af04fSMika Westerberg buf[ret++] = '\n'; 2119e3af04fSMika Westerberg buf[ret] = '\0'; 2129e3af04fSMika Westerberg 2139e3af04fSMika Westerberg kfree(bits); 2149e3af04fSMika Westerberg 2159e3af04fSMika Westerberg return ret; 2169e3af04fSMika Westerberg } 2179e3af04fSMika Westerberg 2189e3af04fSMika Westerberg /** 2199e3af04fSMika Westerberg * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap 2209e3af04fSMika Westerberg * @ddata: pointer to drvdata 2219e3af04fSMika Westerberg * @buf: buffer from userspace that contains stringified bitmap 2229e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 2239e3af04fSMika Westerberg * 2249e3af04fSMika Westerberg * This function parses stringified bitmap from @buf and disables/enables 225a16ca239SDmitry Torokhov * GPIO buttons accordingly. Returns 0 on success and negative error 2269e3af04fSMika Westerberg * on failure. 2279e3af04fSMika Westerberg */ 2289e3af04fSMika Westerberg static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, 2299e3af04fSMika Westerberg const char *buf, unsigned int type) 2309e3af04fSMika Westerberg { 2319e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 232*8679ee42SDmitry Torokhov const unsigned long *bitmap = get_bm_events_by_type(ddata->input, type); 2339e3af04fSMika Westerberg unsigned long *bits; 2349e3af04fSMika Westerberg ssize_t error; 2359e3af04fSMika Westerberg int i; 2369e3af04fSMika Westerberg 2379e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 2389e3af04fSMika Westerberg if (!bits) 2399e3af04fSMika Westerberg return -ENOMEM; 2409e3af04fSMika Westerberg 2419e3af04fSMika Westerberg error = bitmap_parselist(buf, bits, n_events); 2429e3af04fSMika Westerberg if (error) 2439e3af04fSMika Westerberg goto out; 2449e3af04fSMika Westerberg 2459e3af04fSMika Westerberg /* First validate */ 246*8679ee42SDmitry Torokhov if (!bitmap_subset(bits, bitmap, n_events)) { 247*8679ee42SDmitry Torokhov error = -EINVAL; 248*8679ee42SDmitry Torokhov goto out; 249*8679ee42SDmitry Torokhov } 250*8679ee42SDmitry Torokhov 251219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2529e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2539e3af04fSMika Westerberg 2549e3af04fSMika Westerberg if (bdata->button->type != type) 2559e3af04fSMika Westerberg continue; 2569e3af04fSMika Westerberg 2579e3af04fSMika Westerberg if (test_bit(bdata->button->code, bits) && 2589e3af04fSMika Westerberg !bdata->button->can_disable) { 2599e3af04fSMika Westerberg error = -EINVAL; 2609e3af04fSMika Westerberg goto out; 2619e3af04fSMika Westerberg } 2629e3af04fSMika Westerberg } 2639e3af04fSMika Westerberg 2649e3af04fSMika Westerberg mutex_lock(&ddata->disable_lock); 2659e3af04fSMika Westerberg 266219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2679e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2689e3af04fSMika Westerberg 2699e3af04fSMika Westerberg if (bdata->button->type != type) 2709e3af04fSMika Westerberg continue; 2719e3af04fSMika Westerberg 2729e3af04fSMika Westerberg if (test_bit(bdata->button->code, bits)) 2739e3af04fSMika Westerberg gpio_keys_disable_button(bdata); 2749e3af04fSMika Westerberg else 2759e3af04fSMika Westerberg gpio_keys_enable_button(bdata); 2769e3af04fSMika Westerberg } 2779e3af04fSMika Westerberg 2789e3af04fSMika Westerberg mutex_unlock(&ddata->disable_lock); 2799e3af04fSMika Westerberg 2809e3af04fSMika Westerberg out: 2819e3af04fSMika Westerberg kfree(bits); 2829e3af04fSMika Westerberg return error; 2839e3af04fSMika Westerberg } 2849e3af04fSMika Westerberg 2859e3af04fSMika Westerberg #define ATTR_SHOW_FN(name, type, only_disabled) \ 2869e3af04fSMika Westerberg static ssize_t gpio_keys_show_##name(struct device *dev, \ 2879e3af04fSMika Westerberg struct device_attribute *attr, \ 2889e3af04fSMika Westerberg char *buf) \ 2899e3af04fSMika Westerberg { \ 2909e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 2919e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 2929e3af04fSMika Westerberg \ 2939e3af04fSMika Westerberg return gpio_keys_attr_show_helper(ddata, buf, \ 2949e3af04fSMika Westerberg type, only_disabled); \ 2959e3af04fSMika Westerberg } 2969e3af04fSMika Westerberg 2979e3af04fSMika Westerberg ATTR_SHOW_FN(keys, EV_KEY, false); 2989e3af04fSMika Westerberg ATTR_SHOW_FN(switches, EV_SW, false); 2999e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_keys, EV_KEY, true); 3009e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_switches, EV_SW, true); 3019e3af04fSMika Westerberg 3029e3af04fSMika Westerberg /* 3039e3af04fSMika Westerberg * ATTRIBUTES: 3049e3af04fSMika Westerberg * 3059e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/keys [ro] 3069e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/switches [ro] 3079e3af04fSMika Westerberg */ 3089e3af04fSMika Westerberg static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL); 3099e3af04fSMika Westerberg static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL); 3109e3af04fSMika Westerberg 3119e3af04fSMika Westerberg #define ATTR_STORE_FN(name, type) \ 3129e3af04fSMika Westerberg static ssize_t gpio_keys_store_##name(struct device *dev, \ 3139e3af04fSMika Westerberg struct device_attribute *attr, \ 3149e3af04fSMika Westerberg const char *buf, \ 3159e3af04fSMika Westerberg size_t count) \ 3169e3af04fSMika Westerberg { \ 3179e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 3189e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 3199e3af04fSMika Westerberg ssize_t error; \ 3209e3af04fSMika Westerberg \ 3219e3af04fSMika Westerberg error = gpio_keys_attr_store_helper(ddata, buf, type); \ 3229e3af04fSMika Westerberg if (error) \ 3239e3af04fSMika Westerberg return error; \ 3249e3af04fSMika Westerberg \ 3259e3af04fSMika Westerberg return count; \ 3269e3af04fSMika Westerberg } 3279e3af04fSMika Westerberg 3289e3af04fSMika Westerberg ATTR_STORE_FN(disabled_keys, EV_KEY); 3299e3af04fSMika Westerberg ATTR_STORE_FN(disabled_switches, EV_SW); 3309e3af04fSMika Westerberg 3319e3af04fSMika Westerberg /* 3329e3af04fSMika Westerberg * ATTRIBUTES: 3339e3af04fSMika Westerberg * 3349e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disabled_keys [rw] 3359e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disables_switches [rw] 3369e3af04fSMika Westerberg */ 3379e3af04fSMika Westerberg static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO, 3389e3af04fSMika Westerberg gpio_keys_show_disabled_keys, 3399e3af04fSMika Westerberg gpio_keys_store_disabled_keys); 3409e3af04fSMika Westerberg static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO, 3419e3af04fSMika Westerberg gpio_keys_show_disabled_switches, 3429e3af04fSMika Westerberg gpio_keys_store_disabled_switches); 3439e3af04fSMika Westerberg 3449e3af04fSMika Westerberg static struct attribute *gpio_keys_attrs[] = { 3459e3af04fSMika Westerberg &dev_attr_keys.attr, 3469e3af04fSMika Westerberg &dev_attr_switches.attr, 3479e3af04fSMika Westerberg &dev_attr_disabled_keys.attr, 3489e3af04fSMika Westerberg &dev_attr_disabled_switches.attr, 3499e3af04fSMika Westerberg NULL, 3509e3af04fSMika Westerberg }; 3519e3af04fSMika Westerberg 3529e3af04fSMika Westerberg static struct attribute_group gpio_keys_attr_group = { 3539e3af04fSMika Westerberg .attrs = gpio_keys_attrs, 3549e3af04fSMika Westerberg }; 3559e3af04fSMika Westerberg 356d8ee4a1cSLaxman Dewangan static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) 35778a56aabSPhil Blundell { 358d9080921SDmitry Torokhov const struct gpio_keys_button *button = bdata->button; 359ce25d7e9SUwe Kleine-König struct input_dev *input = bdata->input; 36084767d00SRoman Moravcik unsigned int type = button->type ?: EV_KEY; 36177fa0554SBjorn Andersson int state = gpio_get_value_cansleep(button->gpio); 36284767d00SRoman Moravcik 36377fa0554SBjorn Andersson if (state < 0) { 36477fa0554SBjorn Andersson dev_err(input->dev.parent, "failed to get gpio state\n"); 36577fa0554SBjorn Andersson return; 36677fa0554SBjorn Andersson } 36777fa0554SBjorn Andersson 36877fa0554SBjorn Andersson state = (state ? 1 : 0) ^ button->active_low; 36992a47674SAlexander Stein if (type == EV_ABS) { 37092a47674SAlexander Stein if (state) 37192a47674SAlexander Stein input_event(input, type, button->code, button->value); 37292a47674SAlexander Stein } else { 37384767d00SRoman Moravcik input_event(input, type, button->code, !!state); 37492a47674SAlexander Stein } 37578a56aabSPhil Blundell input_sync(input); 376a33466e3SDmitry Baryshkov } 377a33466e3SDmitry Baryshkov 378d8ee4a1cSLaxman Dewangan static void gpio_keys_gpio_work_func(struct work_struct *work) 3796ee88d71SDaniel Mack { 3806ee88d71SDaniel Mack struct gpio_button_data *bdata = 3818ed92556SDmitry Torokhov container_of(work, struct gpio_button_data, work.work); 3826ee88d71SDaniel Mack 383d8ee4a1cSLaxman Dewangan gpio_keys_gpio_report_event(bdata); 3842fba26c6SNeilBrown 3852fba26c6SNeilBrown if (bdata->button->wakeup) 3862fba26c6SNeilBrown pm_relax(bdata->input->dev.parent); 3876ee88d71SDaniel Mack } 3886ee88d71SDaniel Mack 389d8ee4a1cSLaxman Dewangan static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) 390a33466e3SDmitry Baryshkov { 39157ffe9d5SUwe Kleine-König struct gpio_button_data *bdata = dev_id; 392a33466e3SDmitry Baryshkov 393d8ee4a1cSLaxman Dewangan BUG_ON(irq != bdata->irq); 394a33466e3SDmitry Baryshkov 3952fba26c6SNeilBrown if (bdata->button->wakeup) 3962fba26c6SNeilBrown pm_stay_awake(bdata->input->dev.parent); 3978ed92556SDmitry Torokhov 3988ed92556SDmitry Torokhov mod_delayed_work(system_wq, 3998ed92556SDmitry Torokhov &bdata->work, 4008ed92556SDmitry Torokhov msecs_to_jiffies(bdata->software_debounce)); 401a33466e3SDmitry Baryshkov 4021164ec1aSDavid Brownell return IRQ_HANDLED; 40378a56aabSPhil Blundell } 40478a56aabSPhil Blundell 405d8ee4a1cSLaxman Dewangan static void gpio_keys_irq_timer(unsigned long _data) 406d8ee4a1cSLaxman Dewangan { 407d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = (struct gpio_button_data *)_data; 408d8ee4a1cSLaxman Dewangan struct input_dev *input = bdata->input; 409d8ee4a1cSLaxman Dewangan unsigned long flags; 410d8ee4a1cSLaxman Dewangan 411d8ee4a1cSLaxman Dewangan spin_lock_irqsave(&bdata->lock, flags); 412d8ee4a1cSLaxman Dewangan if (bdata->key_pressed) { 413d8ee4a1cSLaxman Dewangan input_event(input, EV_KEY, bdata->button->code, 0); 414d8ee4a1cSLaxman Dewangan input_sync(input); 415d8ee4a1cSLaxman Dewangan bdata->key_pressed = false; 416d8ee4a1cSLaxman Dewangan } 417d8ee4a1cSLaxman Dewangan spin_unlock_irqrestore(&bdata->lock, flags); 418d8ee4a1cSLaxman Dewangan } 419d8ee4a1cSLaxman Dewangan 420d8ee4a1cSLaxman Dewangan static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) 421d8ee4a1cSLaxman Dewangan { 422d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = dev_id; 423d8ee4a1cSLaxman Dewangan const struct gpio_keys_button *button = bdata->button; 424d8ee4a1cSLaxman Dewangan struct input_dev *input = bdata->input; 425d8ee4a1cSLaxman Dewangan unsigned long flags; 426d8ee4a1cSLaxman Dewangan 427d8ee4a1cSLaxman Dewangan BUG_ON(irq != bdata->irq); 428d8ee4a1cSLaxman Dewangan 429d8ee4a1cSLaxman Dewangan spin_lock_irqsave(&bdata->lock, flags); 430d8ee4a1cSLaxman Dewangan 431d8ee4a1cSLaxman Dewangan if (!bdata->key_pressed) { 4322fba26c6SNeilBrown if (bdata->button->wakeup) 4332fba26c6SNeilBrown pm_wakeup_event(bdata->input->dev.parent, 0); 4342fba26c6SNeilBrown 435d8ee4a1cSLaxman Dewangan input_event(input, EV_KEY, button->code, 1); 436d8ee4a1cSLaxman Dewangan input_sync(input); 437d8ee4a1cSLaxman Dewangan 4388ed92556SDmitry Torokhov if (!bdata->release_delay) { 439d8ee4a1cSLaxman Dewangan input_event(input, EV_KEY, button->code, 0); 440d8ee4a1cSLaxman Dewangan input_sync(input); 441d8ee4a1cSLaxman Dewangan goto out; 442d8ee4a1cSLaxman Dewangan } 443d8ee4a1cSLaxman Dewangan 444d8ee4a1cSLaxman Dewangan bdata->key_pressed = true; 445d8ee4a1cSLaxman Dewangan } 446d8ee4a1cSLaxman Dewangan 4478ed92556SDmitry Torokhov if (bdata->release_delay) 4488ed92556SDmitry Torokhov mod_timer(&bdata->release_timer, 4498ed92556SDmitry Torokhov jiffies + msecs_to_jiffies(bdata->release_delay)); 450d8ee4a1cSLaxman Dewangan out: 451d8ee4a1cSLaxman Dewangan spin_unlock_irqrestore(&bdata->lock, flags); 452d8ee4a1cSLaxman Dewangan return IRQ_HANDLED; 453d8ee4a1cSLaxman Dewangan } 454d8ee4a1cSLaxman Dewangan 45527245519SAlexander Shiyan static void gpio_keys_quiesce_key(void *data) 45627245519SAlexander Shiyan { 45727245519SAlexander Shiyan struct gpio_button_data *bdata = data; 45827245519SAlexander Shiyan 4598ed92556SDmitry Torokhov if (gpio_is_valid(bdata->button->gpio)) 4608ed92556SDmitry Torokhov cancel_delayed_work_sync(&bdata->work); 4618ed92556SDmitry Torokhov else 4628ed92556SDmitry Torokhov del_timer_sync(&bdata->release_timer); 46327245519SAlexander Shiyan } 46427245519SAlexander Shiyan 4655298cc4cSBill Pemberton static int gpio_keys_setup_key(struct platform_device *pdev, 466d9080921SDmitry Torokhov struct input_dev *input, 467bc8f1eafSBen Dooks struct gpio_button_data *bdata, 468d9080921SDmitry Torokhov const struct gpio_keys_button *button) 469bc8f1eafSBen Dooks { 47092a47674SAlexander Stein const char *desc = button->desc ? button->desc : "gpio_keys"; 4719e3af04fSMika Westerberg struct device *dev = &pdev->dev; 472d8ee4a1cSLaxman Dewangan irq_handler_t isr; 4739e3af04fSMika Westerberg unsigned long irqflags; 47427245519SAlexander Shiyan int irq; 47527245519SAlexander Shiyan int error; 476bc8f1eafSBen Dooks 477d9080921SDmitry Torokhov bdata->input = input; 478d9080921SDmitry Torokhov bdata->button = button; 479d8ee4a1cSLaxman Dewangan spin_lock_init(&bdata->lock); 480d8ee4a1cSLaxman Dewangan 481d8ee4a1cSLaxman Dewangan if (gpio_is_valid(button->gpio)) { 482bc8f1eafSBen Dooks 48327245519SAlexander Shiyan error = devm_gpio_request_one(&pdev->dev, button->gpio, 48427245519SAlexander Shiyan GPIOF_IN, desc); 485bc8f1eafSBen Dooks if (error < 0) { 486d8ee4a1cSLaxman Dewangan dev_err(dev, "Failed to request GPIO %d, error %d\n", 487bc8f1eafSBen Dooks button->gpio, error); 488d8ee4a1cSLaxman Dewangan return error; 489bc8f1eafSBen Dooks } 490bc8f1eafSBen Dooks 49128ed684fSGrazvydas Ignotas if (button->debounce_interval) { 49228ed684fSGrazvydas Ignotas error = gpio_set_debounce(button->gpio, 49328ed684fSGrazvydas Ignotas button->debounce_interval * 1000); 49428ed684fSGrazvydas Ignotas /* use timer if gpiolib doesn't provide debounce */ 49528ed684fSGrazvydas Ignotas if (error < 0) 4968ed92556SDmitry Torokhov bdata->software_debounce = 497d8ee4a1cSLaxman Dewangan button->debounce_interval; 49828ed684fSGrazvydas Ignotas } 49928ed684fSGrazvydas Ignotas 50097d86e07SDmitry Torokhov if (button->irq) { 50197d86e07SDmitry Torokhov bdata->irq = button->irq; 50297d86e07SDmitry Torokhov } else { 503bc8f1eafSBen Dooks irq = gpio_to_irq(button->gpio); 504bc8f1eafSBen Dooks if (irq < 0) { 505bc8f1eafSBen Dooks error = irq; 506d8ee4a1cSLaxman Dewangan dev_err(dev, 507d8ee4a1cSLaxman Dewangan "Unable to get irq number for GPIO %d, error %d\n", 508bc8f1eafSBen Dooks button->gpio, error); 50927245519SAlexander Shiyan return error; 510d8ee4a1cSLaxman Dewangan } 511d8ee4a1cSLaxman Dewangan bdata->irq = irq; 51297d86e07SDmitry Torokhov } 513d8ee4a1cSLaxman Dewangan 5148ed92556SDmitry Torokhov INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); 515d8ee4a1cSLaxman Dewangan 516d8ee4a1cSLaxman Dewangan isr = gpio_keys_gpio_isr; 517d8ee4a1cSLaxman Dewangan irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; 518d8ee4a1cSLaxman Dewangan 519d8ee4a1cSLaxman Dewangan } else { 520d8ee4a1cSLaxman Dewangan if (!button->irq) { 521d8ee4a1cSLaxman Dewangan dev_err(dev, "No IRQ specified\n"); 522d8ee4a1cSLaxman Dewangan return -EINVAL; 523d8ee4a1cSLaxman Dewangan } 524d8ee4a1cSLaxman Dewangan bdata->irq = button->irq; 525d8ee4a1cSLaxman Dewangan 526d8ee4a1cSLaxman Dewangan if (button->type && button->type != EV_KEY) { 527d8ee4a1cSLaxman Dewangan dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); 528d8ee4a1cSLaxman Dewangan return -EINVAL; 529bc8f1eafSBen Dooks } 530bc8f1eafSBen Dooks 5318ed92556SDmitry Torokhov bdata->release_delay = button->debounce_interval; 5328ed92556SDmitry Torokhov setup_timer(&bdata->release_timer, 533d8ee4a1cSLaxman Dewangan gpio_keys_irq_timer, (unsigned long)bdata); 534d8ee4a1cSLaxman Dewangan 535d8ee4a1cSLaxman Dewangan isr = gpio_keys_irq_isr; 536d8ee4a1cSLaxman Dewangan irqflags = 0; 537d8ee4a1cSLaxman Dewangan } 538d8ee4a1cSLaxman Dewangan 539d8ee4a1cSLaxman Dewangan input_set_capability(input, button->type ?: EV_KEY, button->code); 540d8ee4a1cSLaxman Dewangan 5419e3af04fSMika Westerberg /* 5428ed92556SDmitry Torokhov * Install custom action to cancel release timer and 54327245519SAlexander Shiyan * workqueue item. 54427245519SAlexander Shiyan */ 54527245519SAlexander Shiyan error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); 54627245519SAlexander Shiyan if (error) { 54727245519SAlexander Shiyan dev_err(&pdev->dev, 54827245519SAlexander Shiyan "failed to register quiesce action, error: %d\n", 54927245519SAlexander Shiyan error); 55027245519SAlexander Shiyan return error; 55127245519SAlexander Shiyan } 55227245519SAlexander Shiyan 55327245519SAlexander Shiyan /* 5549e3af04fSMika Westerberg * If platform has specified that the button can be disabled, 5559e3af04fSMika Westerberg * we don't want it to share the interrupt line. 5569e3af04fSMika Westerberg */ 5579e3af04fSMika Westerberg if (!button->can_disable) 5589e3af04fSMika Westerberg irqflags |= IRQF_SHARED; 5599e3af04fSMika Westerberg 56027245519SAlexander Shiyan error = devm_request_any_context_irq(&pdev->dev, bdata->irq, 56127245519SAlexander Shiyan isr, irqflags, desc, bdata); 56294a8cab8SPhilippe Langlais if (error < 0) { 563bc8f1eafSBen Dooks dev_err(dev, "Unable to claim irq %d; error %d\n", 564d8ee4a1cSLaxman Dewangan bdata->irq, error); 56527245519SAlexander Shiyan return error; 566bc8f1eafSBen Dooks } 567bc8f1eafSBen Dooks 568bc8f1eafSBen Dooks return 0; 569bc8f1eafSBen Dooks } 570bc8f1eafSBen Dooks 5715b76d7b4SDmitry Torokhov static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) 5725b76d7b4SDmitry Torokhov { 5735b76d7b4SDmitry Torokhov struct input_dev *input = ddata->input; 5745b76d7b4SDmitry Torokhov int i; 5755b76d7b4SDmitry Torokhov 5765b76d7b4SDmitry Torokhov for (i = 0; i < ddata->pdata->nbuttons; i++) { 5775b76d7b4SDmitry Torokhov struct gpio_button_data *bdata = &ddata->data[i]; 5785b76d7b4SDmitry Torokhov if (gpio_is_valid(bdata->button->gpio)) 5795b76d7b4SDmitry Torokhov gpio_keys_gpio_report_event(bdata); 5805b76d7b4SDmitry Torokhov } 5815b76d7b4SDmitry Torokhov input_sync(input); 5825b76d7b4SDmitry Torokhov } 5835b76d7b4SDmitry Torokhov 584173bdd74SShubhrajyoti D static int gpio_keys_open(struct input_dev *input) 585173bdd74SShubhrajyoti D { 586173bdd74SShubhrajyoti D struct gpio_keys_drvdata *ddata = input_get_drvdata(input); 587219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = ddata->pdata; 5885b76d7b4SDmitry Torokhov int error; 589173bdd74SShubhrajyoti D 5905b76d7b4SDmitry Torokhov if (pdata->enable) { 5915b76d7b4SDmitry Torokhov error = pdata->enable(input->dev.parent); 5925b76d7b4SDmitry Torokhov if (error) 5935b76d7b4SDmitry Torokhov return error; 5945b76d7b4SDmitry Torokhov } 5955b76d7b4SDmitry Torokhov 5965b76d7b4SDmitry Torokhov /* Report current state of buttons that are connected to GPIOs */ 5975b76d7b4SDmitry Torokhov gpio_keys_report_state(ddata); 5985b76d7b4SDmitry Torokhov 5995b76d7b4SDmitry Torokhov return 0; 600173bdd74SShubhrajyoti D } 601173bdd74SShubhrajyoti D 602173bdd74SShubhrajyoti D static void gpio_keys_close(struct input_dev *input) 603173bdd74SShubhrajyoti D { 604173bdd74SShubhrajyoti D struct gpio_keys_drvdata *ddata = input_get_drvdata(input); 605219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = ddata->pdata; 606173bdd74SShubhrajyoti D 607219edc71SAlexandre Pereira da Silva if (pdata->disable) 608219edc71SAlexandre Pereira da Silva pdata->disable(input->dev.parent); 609173bdd74SShubhrajyoti D } 610173bdd74SShubhrajyoti D 611fd05d089SDavid Jander /* 612fd05d089SDavid Jander * Handlers for alternative sources of platform_data 613fd05d089SDavid Jander */ 614219edc71SAlexandre Pereira da Silva 615fd05d089SDavid Jander #ifdef CONFIG_OF 616fd05d089SDavid Jander /* 617fd05d089SDavid Jander * Translate OpenFirmware node properties into platform_data 618fd05d089SDavid Jander */ 6195298cc4cSBill Pemberton static struct gpio_keys_platform_data * 620219edc71SAlexandre Pereira da Silva gpio_keys_get_devtree_pdata(struct device *dev) 621fd05d089SDavid Jander { 622fd05d089SDavid Jander struct device_node *node, *pp; 623219edc71SAlexandre Pereira da Silva struct gpio_keys_platform_data *pdata; 624219edc71SAlexandre Pereira da Silva struct gpio_keys_button *button; 625219edc71SAlexandre Pereira da Silva int error; 626219edc71SAlexandre Pereira da Silva int nbuttons; 627fd05d089SDavid Jander int i; 628fd05d089SDavid Jander 629fd05d089SDavid Jander node = dev->of_node; 6305d422f2eSAndy Shevchenko if (!node) 6315d422f2eSAndy Shevchenko return ERR_PTR(-ENODEV); 632fd05d089SDavid Jander 633219edc71SAlexandre Pereira da Silva nbuttons = of_get_child_count(node); 6345d422f2eSAndy Shevchenko if (nbuttons == 0) 6355d422f2eSAndy Shevchenko return ERR_PTR(-ENODEV); 636219edc71SAlexandre Pereira da Silva 6375d422f2eSAndy Shevchenko pdata = devm_kzalloc(dev, 6385d422f2eSAndy Shevchenko sizeof(*pdata) + nbuttons * sizeof(*button), 639219edc71SAlexandre Pereira da Silva GFP_KERNEL); 6405d422f2eSAndy Shevchenko if (!pdata) 6415d422f2eSAndy Shevchenko return ERR_PTR(-ENOMEM); 642219edc71SAlexandre Pereira da Silva 643219edc71SAlexandre Pereira da Silva pdata->buttons = (struct gpio_keys_button *)(pdata + 1); 644219edc71SAlexandre Pereira da Silva pdata->nbuttons = nbuttons; 645fd05d089SDavid Jander 646cca84699STobias Klauser pdata->rep = !!of_get_property(node, "autorepeat", NULL); 647fd05d089SDavid Jander 648fd05d089SDavid Jander i = 0; 649219edc71SAlexandre Pereira da Silva for_each_child_of_node(node, pp) { 650fd05d089SDavid Jander enum of_gpio_flags flags; 651fd05d089SDavid Jander 6521d6a0136SFabio Estevam button = &pdata->buttons[i++]; 6531d6a0136SFabio Estevam 65497d86e07SDmitry Torokhov button->gpio = of_get_gpio_flags(pp, 0, &flags); 65597d86e07SDmitry Torokhov if (button->gpio < 0) { 65697d86e07SDmitry Torokhov error = button->gpio; 65797d86e07SDmitry Torokhov if (error != -ENOENT) { 658e324ce61SDmitry Torokhov if (error != -EPROBE_DEFER) 659e324ce61SDmitry Torokhov dev_err(dev, 660e324ce61SDmitry Torokhov "Failed to get gpio flags, error: %d\n", 661e324ce61SDmitry Torokhov error); 6625d422f2eSAndy Shevchenko return ERR_PTR(error); 663e324ce61SDmitry Torokhov } 66497d86e07SDmitry Torokhov } else { 66597d86e07SDmitry Torokhov button->active_low = flags & OF_GPIO_ACTIVE_LOW; 666f2d347ffSAlexander Stein } 667fd05d089SDavid Jander 66897d86e07SDmitry Torokhov button->irq = irq_of_parse_and_map(pp, 0); 66997d86e07SDmitry Torokhov 67097d86e07SDmitry Torokhov if (!gpio_is_valid(button->gpio) && !button->irq) { 67197d86e07SDmitry Torokhov dev_err(dev, "Found button without gpios or irqs\n"); 67297d86e07SDmitry Torokhov return ERR_PTR(-EINVAL); 67397d86e07SDmitry Torokhov } 674fd05d089SDavid Jander 675219edc71SAlexandre Pereira da Silva if (of_property_read_u32(pp, "linux,code", &button->code)) { 676219edc71SAlexandre Pereira da Silva dev_err(dev, "Button without keycode: 0x%x\n", 677219edc71SAlexandre Pereira da Silva button->gpio); 6785d422f2eSAndy Shevchenko return ERR_PTR(-EINVAL); 679fd05d089SDavid Jander } 680fd05d089SDavid Jander 681219edc71SAlexandre Pereira da Silva button->desc = of_get_property(pp, "label", NULL); 682fd05d089SDavid Jander 683219edc71SAlexandre Pereira da Silva if (of_property_read_u32(pp, "linux,input-type", &button->type)) 684219edc71SAlexandre Pereira da Silva button->type = EV_KEY; 685fd05d089SDavid Jander 68699b4ffbdSDmitry Torokhov button->wakeup = of_property_read_bool(pp, "wakeup-source") || 68799b4ffbdSDmitry Torokhov /* legacy name */ 68899b4ffbdSDmitry Torokhov of_property_read_bool(pp, "gpio-key,wakeup"); 689219edc71SAlexandre Pereira da Silva 69097d86e07SDmitry Torokhov button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL); 69197d86e07SDmitry Torokhov 692219edc71SAlexandre Pereira da Silva if (of_property_read_u32(pp, "debounce-interval", 693219edc71SAlexandre Pereira da Silva &button->debounce_interval)) 694219edc71SAlexandre Pereira da Silva button->debounce_interval = 5; 695219edc71SAlexandre Pereira da Silva } 696219edc71SAlexandre Pereira da Silva 6975d422f2eSAndy Shevchenko if (pdata->nbuttons == 0) 6985d422f2eSAndy Shevchenko return ERR_PTR(-EINVAL); 699219edc71SAlexandre Pereira da Silva 700219edc71SAlexandre Pereira da Silva return pdata; 701fd05d089SDavid Jander } 702fd05d089SDavid Jander 70322daae31SJingoo Han static const struct of_device_id gpio_keys_of_match[] = { 704fd05d089SDavid Jander { .compatible = "gpio-keys", }, 705fd05d089SDavid Jander { }, 706fd05d089SDavid Jander }; 707fd05d089SDavid Jander MODULE_DEVICE_TABLE(of, gpio_keys_of_match); 708fd05d089SDavid Jander 709fd05d089SDavid Jander #else 710fd05d089SDavid Jander 711219edc71SAlexandre Pereira da Silva static inline struct gpio_keys_platform_data * 712219edc71SAlexandre Pereira da Silva gpio_keys_get_devtree_pdata(struct device *dev) 713fd05d089SDavid Jander { 714219edc71SAlexandre Pereira da Silva return ERR_PTR(-ENODEV); 715fd05d089SDavid Jander } 716fd05d089SDavid Jander 717fd05d089SDavid Jander #endif 718fd05d089SDavid Jander 7195298cc4cSBill Pemberton static int gpio_keys_probe(struct platform_device *pdev) 72078a56aabSPhil Blundell { 721db19fd8bSBen Dooks struct device *dev = &pdev->dev; 722219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); 723219edc71SAlexandre Pereira da Silva struct gpio_keys_drvdata *ddata; 72478a56aabSPhil Blundell struct input_dev *input; 7255d422f2eSAndy Shevchenko size_t size; 72678a56aabSPhil Blundell int i, error; 727e15b0213SAnti Sullin int wakeup = 0; 72878a56aabSPhil Blundell 729fd05d089SDavid Jander if (!pdata) { 730219edc71SAlexandre Pereira da Silva pdata = gpio_keys_get_devtree_pdata(dev); 731219edc71SAlexandre Pereira da Silva if (IS_ERR(pdata)) 732219edc71SAlexandre Pereira da Silva return PTR_ERR(pdata); 733fd05d089SDavid Jander } 734fd05d089SDavid Jander 7355d422f2eSAndy Shevchenko size = sizeof(struct gpio_keys_drvdata) + 7365d422f2eSAndy Shevchenko pdata->nbuttons * sizeof(struct gpio_button_data); 7375d422f2eSAndy Shevchenko ddata = devm_kzalloc(dev, size, GFP_KERNEL); 7385d422f2eSAndy Shevchenko if (!ddata) { 739db19fd8bSBen Dooks dev_err(dev, "failed to allocate state\n"); 7405d422f2eSAndy Shevchenko return -ENOMEM; 7415d422f2eSAndy Shevchenko } 7425d422f2eSAndy Shevchenko 7435d422f2eSAndy Shevchenko input = devm_input_allocate_device(dev); 7445d422f2eSAndy Shevchenko if (!input) { 7455d422f2eSAndy Shevchenko dev_err(dev, "failed to allocate input device\n"); 7465d422f2eSAndy Shevchenko return -ENOMEM; 747a33466e3SDmitry Baryshkov } 74878a56aabSPhil Blundell 749219edc71SAlexandre Pereira da Silva ddata->pdata = pdata; 7509e3af04fSMika Westerberg ddata->input = input; 7519e3af04fSMika Westerberg mutex_init(&ddata->disable_lock); 7529e3af04fSMika Westerberg 753a33466e3SDmitry Baryshkov platform_set_drvdata(pdev, ddata); 754173bdd74SShubhrajyoti D input_set_drvdata(input, ddata); 75578a56aabSPhil Blundell 75646711277SAlexander Stein input->name = pdata->name ? : pdev->name; 75778a56aabSPhil Blundell input->phys = "gpio-keys/input0"; 758469ba4dfSDmitry Torokhov input->dev.parent = &pdev->dev; 759173bdd74SShubhrajyoti D input->open = gpio_keys_open; 760173bdd74SShubhrajyoti D input->close = gpio_keys_close; 76178a56aabSPhil Blundell 76278a56aabSPhil Blundell input->id.bustype = BUS_HOST; 76378a56aabSPhil Blundell input->id.vendor = 0x0001; 76478a56aabSPhil Blundell input->id.product = 0x0001; 76578a56aabSPhil Blundell input->id.version = 0x0100; 76678a56aabSPhil Blundell 767b67b4b11SDominic Curran /* Enable auto repeat feature of Linux input subsystem */ 768b67b4b11SDominic Curran if (pdata->rep) 769b67b4b11SDominic Curran __set_bit(EV_REP, input->evbit); 770b67b4b11SDominic Curran 77178a56aabSPhil Blundell for (i = 0; i < pdata->nbuttons; i++) { 772d9080921SDmitry Torokhov const struct gpio_keys_button *button = &pdata->buttons[i]; 773a33466e3SDmitry Baryshkov struct gpio_button_data *bdata = &ddata->data[i]; 77478a56aabSPhil Blundell 775d9080921SDmitry Torokhov error = gpio_keys_setup_key(pdev, input, bdata, button); 776bc8f1eafSBen Dooks if (error) 77727245519SAlexander Shiyan return error; 77884767d00SRoman Moravcik 779e15b0213SAnti Sullin if (button->wakeup) 780e15b0213SAnti Sullin wakeup = 1; 78178a56aabSPhil Blundell } 78278a56aabSPhil Blundell 7839e3af04fSMika Westerberg error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); 7849e3af04fSMika Westerberg if (error) { 7859e3af04fSMika Westerberg dev_err(dev, "Unable to export keys/switches, error: %d\n", 7869e3af04fSMika Westerberg error); 78727245519SAlexander Shiyan return error; 7889e3af04fSMika Westerberg } 7899e3af04fSMika Westerberg 79078a56aabSPhil Blundell error = input_register_device(input); 79178a56aabSPhil Blundell if (error) { 7929e3af04fSMika Westerberg dev_err(dev, "Unable to register input device, error: %d\n", 7939e3af04fSMika Westerberg error); 79427245519SAlexander Shiyan goto err_remove_group; 79578a56aabSPhil Blundell } 79678a56aabSPhil Blundell 797e15b0213SAnti Sullin device_init_wakeup(&pdev->dev, wakeup); 798e15b0213SAnti Sullin 79978a56aabSPhil Blundell return 0; 80078a56aabSPhil Blundell 80127245519SAlexander Shiyan err_remove_group: 8029e3af04fSMika Westerberg sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); 80378a56aabSPhil Blundell return error; 80478a56aabSPhil Blundell } 80578a56aabSPhil Blundell 806e2619cf7SBill Pemberton static int gpio_keys_remove(struct platform_device *pdev) 80778a56aabSPhil Blundell { 8089e3af04fSMika Westerberg sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); 8099e3af04fSMika Westerberg 810e15b0213SAnti Sullin device_init_wakeup(&pdev->dev, 0); 811e15b0213SAnti Sullin 81278a56aabSPhil Blundell return 0; 81378a56aabSPhil Blundell } 81478a56aabSPhil Blundell 815bdda8216SDmitry Torokhov #ifdef CONFIG_PM_SLEEP 816ae78e0e0SMike Rapoport static int gpio_keys_suspend(struct device *dev) 817e15b0213SAnti Sullin { 818fd05d089SDavid Jander struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 819dda19a92SJonas Aaberg struct input_dev *input = ddata->input; 820e15b0213SAnti Sullin int i; 821e15b0213SAnti Sullin 822fd05d089SDavid Jander if (device_may_wakeup(dev)) { 823219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 824d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = &ddata->data[i]; 825d8ee4a1cSLaxman Dewangan if (bdata->button->wakeup) 826d8ee4a1cSLaxman Dewangan enable_irq_wake(bdata->irq); 827e15b0213SAnti Sullin } 828dda19a92SJonas Aaberg } else { 829dda19a92SJonas Aaberg mutex_lock(&input->mutex); 830dda19a92SJonas Aaberg if (input->users) 831dda19a92SJonas Aaberg gpio_keys_close(input); 832dda19a92SJonas Aaberg mutex_unlock(&input->mutex); 833e15b0213SAnti Sullin } 834e15b0213SAnti Sullin 835e15b0213SAnti Sullin return 0; 836e15b0213SAnti Sullin } 837e15b0213SAnti Sullin 838ae78e0e0SMike Rapoport static int gpio_keys_resume(struct device *dev) 839e15b0213SAnti Sullin { 840fd05d089SDavid Jander struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 841dda19a92SJonas Aaberg struct input_dev *input = ddata->input; 842dda19a92SJonas Aaberg int error = 0; 843e15b0213SAnti Sullin int i; 844e15b0213SAnti Sullin 845dda19a92SJonas Aaberg if (device_may_wakeup(dev)) { 846219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 847d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = &ddata->data[i]; 848dda19a92SJonas Aaberg if (bdata->button->wakeup) 849d8ee4a1cSLaxman Dewangan disable_irq_wake(bdata->irq); 850e15b0213SAnti Sullin } 851dda19a92SJonas Aaberg } else { 852dda19a92SJonas Aaberg mutex_lock(&input->mutex); 853dda19a92SJonas Aaberg if (input->users) 854dda19a92SJonas Aaberg error = gpio_keys_open(input); 855dda19a92SJonas Aaberg mutex_unlock(&input->mutex); 856dda19a92SJonas Aaberg } 857dda19a92SJonas Aaberg 858dda19a92SJonas Aaberg if (error) 859dda19a92SJonas Aaberg return error; 8605b76d7b4SDmitry Torokhov 8615b76d7b4SDmitry Torokhov gpio_keys_report_state(ddata); 862e15b0213SAnti Sullin return 0; 863e15b0213SAnti Sullin } 864e15b0213SAnti Sullin #endif 865e15b0213SAnti Sullin 866bdda8216SDmitry Torokhov static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); 867bdda8216SDmitry Torokhov 8689b07044cSUwe Kleine-König static struct platform_driver gpio_keys_device_driver = { 86978a56aabSPhil Blundell .probe = gpio_keys_probe, 8701cb0aa88SBill Pemberton .remove = gpio_keys_remove, 87178a56aabSPhil Blundell .driver = { 87278a56aabSPhil Blundell .name = "gpio-keys", 873ae78e0e0SMike Rapoport .pm = &gpio_keys_pm_ops, 874219edc71SAlexandre Pereira da Silva .of_match_table = of_match_ptr(gpio_keys_of_match), 87578a56aabSPhil Blundell } 87678a56aabSPhil Blundell }; 87778a56aabSPhil Blundell 87878a56aabSPhil Blundell static int __init gpio_keys_init(void) 87978a56aabSPhil Blundell { 88078a56aabSPhil Blundell return platform_driver_register(&gpio_keys_device_driver); 88178a56aabSPhil Blundell } 88278a56aabSPhil Blundell 88378a56aabSPhil Blundell static void __exit gpio_keys_exit(void) 88478a56aabSPhil Blundell { 88578a56aabSPhil Blundell platform_driver_unregister(&gpio_keys_device_driver); 88678a56aabSPhil Blundell } 88778a56aabSPhil Blundell 888b2330205SDavid Jander late_initcall(gpio_keys_init); 88978a56aabSPhil Blundell module_exit(gpio_keys_exit); 89078a56aabSPhil Blundell 89178a56aabSPhil Blundell MODULE_LICENSE("GPL"); 89278a56aabSPhil Blundell MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); 8937e2ecdf4SDavid Jander MODULE_DESCRIPTION("Keyboard driver for GPIOs"); 894d7b5247bSKay Sievers MODULE_ALIAS("platform:gpio-keys"); 895