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> 3378a56aabSPhil Blundell 34a33466e3SDmitry Baryshkov struct gpio_button_data { 35d9080921SDmitry Torokhov const struct gpio_keys_button *button; 36a33466e3SDmitry Baryshkov struct input_dev *input; 375feeca3cSGeert Uytterhoeven struct gpio_desc *gpiod; 388ed92556SDmitry Torokhov 39*83e4947aSHans de Goede unsigned short *code; 40*83e4947aSHans de Goede 418ed92556SDmitry Torokhov struct timer_list release_timer; 428ed92556SDmitry Torokhov unsigned int release_delay; /* in msecs, for IRQ-only buttons */ 438ed92556SDmitry Torokhov 448ed92556SDmitry Torokhov struct delayed_work work; 458ed92556SDmitry Torokhov unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */ 468ed92556SDmitry Torokhov 47d8ee4a1cSLaxman Dewangan unsigned int irq; 48d8ee4a1cSLaxman Dewangan spinlock_t lock; 499e3af04fSMika Westerberg bool disabled; 50d8ee4a1cSLaxman Dewangan bool key_pressed; 51a33466e3SDmitry Baryshkov }; 52a33466e3SDmitry Baryshkov 53a33466e3SDmitry Baryshkov struct gpio_keys_drvdata { 54219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata; 55a33466e3SDmitry Baryshkov struct input_dev *input; 569e3af04fSMika Westerberg struct mutex disable_lock; 57*83e4947aSHans de Goede unsigned short *keymap; 58a33466e3SDmitry Baryshkov struct gpio_button_data data[0]; 59a33466e3SDmitry Baryshkov }; 60a33466e3SDmitry Baryshkov 619e3af04fSMika Westerberg /* 629e3af04fSMika Westerberg * SYSFS interface for enabling/disabling keys and switches: 639e3af04fSMika Westerberg * 649e3af04fSMika Westerberg * There are 4 attributes under /sys/devices/platform/gpio-keys/ 659e3af04fSMika Westerberg * keys [ro] - bitmap of keys (EV_KEY) which can be 669e3af04fSMika Westerberg * disabled 679e3af04fSMika Westerberg * switches [ro] - bitmap of switches (EV_SW) which can be 689e3af04fSMika Westerberg * disabled 699e3af04fSMika Westerberg * disabled_keys [rw] - bitmap of keys currently disabled 709e3af04fSMika Westerberg * disabled_switches [rw] - bitmap of switches currently disabled 719e3af04fSMika Westerberg * 729e3af04fSMika Westerberg * Userland can change these values and hence disable event generation 739e3af04fSMika Westerberg * for each key (or switch). Disabling a key means its interrupt line 749e3af04fSMika Westerberg * is disabled. 759e3af04fSMika Westerberg * 769e3af04fSMika Westerberg * For example, if we have following switches set up as gpio-keys: 779e3af04fSMika Westerberg * SW_DOCK = 5 789e3af04fSMika Westerberg * SW_CAMERA_LENS_COVER = 9 799e3af04fSMika Westerberg * SW_KEYPAD_SLIDE = 10 809e3af04fSMika Westerberg * SW_FRONT_PROXIMITY = 11 819e3af04fSMika Westerberg * This is read from switches: 829e3af04fSMika Westerberg * 11-9,5 839e3af04fSMika Westerberg * Next we want to disable proximity (11) and dock (5), we write: 849e3af04fSMika Westerberg * 11,5 859e3af04fSMika Westerberg * to file disabled_switches. Now proximity and dock IRQs are disabled. 869e3af04fSMika Westerberg * This can be verified by reading the file disabled_switches: 879e3af04fSMika Westerberg * 11,5 889e3af04fSMika Westerberg * If we now want to enable proximity (11) switch we write: 899e3af04fSMika Westerberg * 5 909e3af04fSMika Westerberg * to disabled_switches. 919e3af04fSMika Westerberg * 929e3af04fSMika Westerberg * We can disable only those keys which don't allow sharing the irq. 939e3af04fSMika Westerberg */ 949e3af04fSMika Westerberg 959e3af04fSMika Westerberg /** 969e3af04fSMika Westerberg * get_n_events_by_type() - returns maximum number of events per @type 979e3af04fSMika Westerberg * @type: type of button (%EV_KEY, %EV_SW) 989e3af04fSMika Westerberg * 999e3af04fSMika Westerberg * Return value of this function can be used to allocate bitmap 1009e3af04fSMika Westerberg * large enough to hold all bits for given type. 1019e3af04fSMika Westerberg */ 1028679ee42SDmitry Torokhov static int get_n_events_by_type(int type) 1039e3af04fSMika Westerberg { 1049e3af04fSMika Westerberg BUG_ON(type != EV_SW && type != EV_KEY); 1059e3af04fSMika Westerberg 1069e3af04fSMika Westerberg return (type == EV_KEY) ? KEY_CNT : SW_CNT; 1079e3af04fSMika Westerberg } 1089e3af04fSMika Westerberg 1099e3af04fSMika Westerberg /** 1108679ee42SDmitry Torokhov * get_bm_events_by_type() - returns bitmap of supported events per @type 1118679ee42SDmitry Torokhov * @input: input device from which bitmap is retrieved 1128679ee42SDmitry Torokhov * @type: type of button (%EV_KEY, %EV_SW) 1138679ee42SDmitry Torokhov * 1148679ee42SDmitry Torokhov * Return value of this function can be used to allocate bitmap 1158679ee42SDmitry Torokhov * large enough to hold all bits for given type. 1168679ee42SDmitry Torokhov */ 1178679ee42SDmitry Torokhov static const unsigned long *get_bm_events_by_type(struct input_dev *dev, 1188679ee42SDmitry Torokhov int type) 1198679ee42SDmitry Torokhov { 1208679ee42SDmitry Torokhov BUG_ON(type != EV_SW && type != EV_KEY); 1218679ee42SDmitry Torokhov 1228679ee42SDmitry Torokhov return (type == EV_KEY) ? dev->keybit : dev->swbit; 1238679ee42SDmitry Torokhov } 1248679ee42SDmitry Torokhov 1258679ee42SDmitry Torokhov /** 1269e3af04fSMika Westerberg * gpio_keys_disable_button() - disables given GPIO button 1279e3af04fSMika Westerberg * @bdata: button data for button to be disabled 1289e3af04fSMika Westerberg * 1299e3af04fSMika Westerberg * Disables button pointed by @bdata. This is done by masking 1309e3af04fSMika Westerberg * IRQ line. After this function is called, button won't generate 1319e3af04fSMika Westerberg * input events anymore. Note that one can only disable buttons 1329e3af04fSMika Westerberg * that don't share IRQs. 1339e3af04fSMika Westerberg * 1349e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1359e3af04fSMika Westerberg * this function to avoid races when concurrent threads are 1369e3af04fSMika Westerberg * disabling buttons at the same time. 1379e3af04fSMika Westerberg */ 1389e3af04fSMika Westerberg static void gpio_keys_disable_button(struct gpio_button_data *bdata) 1399e3af04fSMika Westerberg { 1409e3af04fSMika Westerberg if (!bdata->disabled) { 1419e3af04fSMika Westerberg /* 1428ed92556SDmitry Torokhov * Disable IRQ and associated timer/work structure. 1439e3af04fSMika Westerberg */ 144d8ee4a1cSLaxman Dewangan disable_irq(bdata->irq); 1458ed92556SDmitry Torokhov 1465feeca3cSGeert Uytterhoeven if (bdata->gpiod) 1478ed92556SDmitry Torokhov cancel_delayed_work_sync(&bdata->work); 1488ed92556SDmitry Torokhov else 1498ed92556SDmitry Torokhov del_timer_sync(&bdata->release_timer); 1509e3af04fSMika Westerberg 1519e3af04fSMika Westerberg bdata->disabled = true; 1529e3af04fSMika Westerberg } 1539e3af04fSMika Westerberg } 1549e3af04fSMika Westerberg 1559e3af04fSMika Westerberg /** 1569e3af04fSMika Westerberg * gpio_keys_enable_button() - enables given GPIO button 1579e3af04fSMika Westerberg * @bdata: button data for button to be disabled 1589e3af04fSMika Westerberg * 1599e3af04fSMika Westerberg * Enables given button pointed by @bdata. 1609e3af04fSMika Westerberg * 1619e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1629e3af04fSMika Westerberg * this function to avoid races with concurrent threads trying 1639e3af04fSMika Westerberg * to enable the same button at the same time. 1649e3af04fSMika Westerberg */ 1659e3af04fSMika Westerberg static void gpio_keys_enable_button(struct gpio_button_data *bdata) 1669e3af04fSMika Westerberg { 1679e3af04fSMika Westerberg if (bdata->disabled) { 168d8ee4a1cSLaxman Dewangan enable_irq(bdata->irq); 1699e3af04fSMika Westerberg bdata->disabled = false; 1709e3af04fSMika Westerberg } 1719e3af04fSMika Westerberg } 1729e3af04fSMika Westerberg 1739e3af04fSMika Westerberg /** 1749e3af04fSMika Westerberg * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons 1759e3af04fSMika Westerberg * @ddata: pointer to drvdata 1769e3af04fSMika Westerberg * @buf: buffer where stringified bitmap is written 1779e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 1789e3af04fSMika Westerberg * @only_disabled: does caller want only those buttons that are 1799e3af04fSMika Westerberg * currently disabled or all buttons that can be 1809e3af04fSMika Westerberg * disabled 1819e3af04fSMika Westerberg * 1829e3af04fSMika Westerberg * This function writes buttons that can be disabled to @buf. If 1839e3af04fSMika Westerberg * @only_disabled is true, then @buf contains only those buttons 1849e3af04fSMika Westerberg * that are currently disabled. Returns 0 on success or negative 1859e3af04fSMika Westerberg * errno on failure. 1869e3af04fSMika Westerberg */ 1879e3af04fSMika Westerberg static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, 1889e3af04fSMika Westerberg char *buf, unsigned int type, 1899e3af04fSMika Westerberg bool only_disabled) 1909e3af04fSMika Westerberg { 1919e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 1929e3af04fSMika Westerberg unsigned long *bits; 1939e3af04fSMika Westerberg ssize_t ret; 1949e3af04fSMika Westerberg int i; 1959e3af04fSMika Westerberg 1969e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 1979e3af04fSMika Westerberg if (!bits) 1989e3af04fSMika Westerberg return -ENOMEM; 1999e3af04fSMika Westerberg 200219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2019e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2029e3af04fSMika Westerberg 2039e3af04fSMika Westerberg if (bdata->button->type != type) 2049e3af04fSMika Westerberg continue; 2059e3af04fSMika Westerberg 2069e3af04fSMika Westerberg if (only_disabled && !bdata->disabled) 2079e3af04fSMika Westerberg continue; 2089e3af04fSMika Westerberg 209*83e4947aSHans de Goede __set_bit(*bdata->code, bits); 2109e3af04fSMika Westerberg } 2119e3af04fSMika Westerberg 2120b480037STejun Heo ret = scnprintf(buf, PAGE_SIZE - 1, "%*pbl", n_events, bits); 2139e3af04fSMika Westerberg buf[ret++] = '\n'; 2149e3af04fSMika Westerberg buf[ret] = '\0'; 2159e3af04fSMika Westerberg 2169e3af04fSMika Westerberg kfree(bits); 2179e3af04fSMika Westerberg 2189e3af04fSMika Westerberg return ret; 2199e3af04fSMika Westerberg } 2209e3af04fSMika Westerberg 2219e3af04fSMika Westerberg /** 2229e3af04fSMika Westerberg * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap 2239e3af04fSMika Westerberg * @ddata: pointer to drvdata 2249e3af04fSMika Westerberg * @buf: buffer from userspace that contains stringified bitmap 2259e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 2269e3af04fSMika Westerberg * 2279e3af04fSMika Westerberg * This function parses stringified bitmap from @buf and disables/enables 228a16ca239SDmitry Torokhov * GPIO buttons accordingly. Returns 0 on success and negative error 2299e3af04fSMika Westerberg * on failure. 2309e3af04fSMika Westerberg */ 2319e3af04fSMika Westerberg static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, 2329e3af04fSMika Westerberg const char *buf, unsigned int type) 2339e3af04fSMika Westerberg { 2349e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 2358679ee42SDmitry Torokhov const unsigned long *bitmap = get_bm_events_by_type(ddata->input, type); 2369e3af04fSMika Westerberg unsigned long *bits; 2379e3af04fSMika Westerberg ssize_t error; 2389e3af04fSMika Westerberg int i; 2399e3af04fSMika Westerberg 2409e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 2419e3af04fSMika Westerberg if (!bits) 2429e3af04fSMika Westerberg return -ENOMEM; 2439e3af04fSMika Westerberg 2449e3af04fSMika Westerberg error = bitmap_parselist(buf, bits, n_events); 2459e3af04fSMika Westerberg if (error) 2469e3af04fSMika Westerberg goto out; 2479e3af04fSMika Westerberg 2489e3af04fSMika Westerberg /* First validate */ 2498679ee42SDmitry Torokhov if (!bitmap_subset(bits, bitmap, n_events)) { 2508679ee42SDmitry Torokhov error = -EINVAL; 2518679ee42SDmitry Torokhov goto out; 2528679ee42SDmitry Torokhov } 2538679ee42SDmitry Torokhov 254219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2559e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2569e3af04fSMika Westerberg 2579e3af04fSMika Westerberg if (bdata->button->type != type) 2589e3af04fSMika Westerberg continue; 2599e3af04fSMika Westerberg 260*83e4947aSHans de Goede if (test_bit(*bdata->code, bits) && 2619e3af04fSMika Westerberg !bdata->button->can_disable) { 2629e3af04fSMika Westerberg error = -EINVAL; 2639e3af04fSMika Westerberg goto out; 2649e3af04fSMika Westerberg } 2659e3af04fSMika Westerberg } 2669e3af04fSMika Westerberg 2679e3af04fSMika Westerberg mutex_lock(&ddata->disable_lock); 2689e3af04fSMika Westerberg 269219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2709e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2719e3af04fSMika Westerberg 2729e3af04fSMika Westerberg if (bdata->button->type != type) 2739e3af04fSMika Westerberg continue; 2749e3af04fSMika Westerberg 275*83e4947aSHans de Goede if (test_bit(*bdata->code, bits)) 2769e3af04fSMika Westerberg gpio_keys_disable_button(bdata); 2779e3af04fSMika Westerberg else 2789e3af04fSMika Westerberg gpio_keys_enable_button(bdata); 2799e3af04fSMika Westerberg } 2809e3af04fSMika Westerberg 2819e3af04fSMika Westerberg mutex_unlock(&ddata->disable_lock); 2829e3af04fSMika Westerberg 2839e3af04fSMika Westerberg out: 2849e3af04fSMika Westerberg kfree(bits); 2859e3af04fSMika Westerberg return error; 2869e3af04fSMika Westerberg } 2879e3af04fSMika Westerberg 2889e3af04fSMika Westerberg #define ATTR_SHOW_FN(name, type, only_disabled) \ 2899e3af04fSMika Westerberg static ssize_t gpio_keys_show_##name(struct device *dev, \ 2909e3af04fSMika Westerberg struct device_attribute *attr, \ 2919e3af04fSMika Westerberg char *buf) \ 2929e3af04fSMika Westerberg { \ 2939e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 2949e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 2959e3af04fSMika Westerberg \ 2969e3af04fSMika Westerberg return gpio_keys_attr_show_helper(ddata, buf, \ 2979e3af04fSMika Westerberg type, only_disabled); \ 2989e3af04fSMika Westerberg } 2999e3af04fSMika Westerberg 3009e3af04fSMika Westerberg ATTR_SHOW_FN(keys, EV_KEY, false); 3019e3af04fSMika Westerberg ATTR_SHOW_FN(switches, EV_SW, false); 3029e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_keys, EV_KEY, true); 3039e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_switches, EV_SW, true); 3049e3af04fSMika Westerberg 3059e3af04fSMika Westerberg /* 3069e3af04fSMika Westerberg * ATTRIBUTES: 3079e3af04fSMika Westerberg * 3089e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/keys [ro] 3099e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/switches [ro] 3109e3af04fSMika Westerberg */ 3119e3af04fSMika Westerberg static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL); 3129e3af04fSMika Westerberg static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL); 3139e3af04fSMika Westerberg 3149e3af04fSMika Westerberg #define ATTR_STORE_FN(name, type) \ 3159e3af04fSMika Westerberg static ssize_t gpio_keys_store_##name(struct device *dev, \ 3169e3af04fSMika Westerberg struct device_attribute *attr, \ 3179e3af04fSMika Westerberg const char *buf, \ 3189e3af04fSMika Westerberg size_t count) \ 3199e3af04fSMika Westerberg { \ 3209e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 3219e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 3229e3af04fSMika Westerberg ssize_t error; \ 3239e3af04fSMika Westerberg \ 3249e3af04fSMika Westerberg error = gpio_keys_attr_store_helper(ddata, buf, type); \ 3259e3af04fSMika Westerberg if (error) \ 3269e3af04fSMika Westerberg return error; \ 3279e3af04fSMika Westerberg \ 3289e3af04fSMika Westerberg return count; \ 3299e3af04fSMika Westerberg } 3309e3af04fSMika Westerberg 3319e3af04fSMika Westerberg ATTR_STORE_FN(disabled_keys, EV_KEY); 3329e3af04fSMika Westerberg ATTR_STORE_FN(disabled_switches, EV_SW); 3339e3af04fSMika Westerberg 3349e3af04fSMika Westerberg /* 3359e3af04fSMika Westerberg * ATTRIBUTES: 3369e3af04fSMika Westerberg * 3379e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disabled_keys [rw] 3389e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disables_switches [rw] 3399e3af04fSMika Westerberg */ 3409e3af04fSMika Westerberg static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO, 3419e3af04fSMika Westerberg gpio_keys_show_disabled_keys, 3429e3af04fSMika Westerberg gpio_keys_store_disabled_keys); 3439e3af04fSMika Westerberg static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO, 3449e3af04fSMika Westerberg gpio_keys_show_disabled_switches, 3459e3af04fSMika Westerberg gpio_keys_store_disabled_switches); 3469e3af04fSMika Westerberg 3479e3af04fSMika Westerberg static struct attribute *gpio_keys_attrs[] = { 3489e3af04fSMika Westerberg &dev_attr_keys.attr, 3499e3af04fSMika Westerberg &dev_attr_switches.attr, 3509e3af04fSMika Westerberg &dev_attr_disabled_keys.attr, 3519e3af04fSMika Westerberg &dev_attr_disabled_switches.attr, 3529e3af04fSMika Westerberg NULL, 3539e3af04fSMika Westerberg }; 3549e3af04fSMika Westerberg 3559e3af04fSMika Westerberg static struct attribute_group gpio_keys_attr_group = { 3569e3af04fSMika Westerberg .attrs = gpio_keys_attrs, 3579e3af04fSMika Westerberg }; 3589e3af04fSMika Westerberg 359d8ee4a1cSLaxman Dewangan static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) 36078a56aabSPhil Blundell { 361d9080921SDmitry Torokhov const struct gpio_keys_button *button = bdata->button; 362ce25d7e9SUwe Kleine-König struct input_dev *input = bdata->input; 36384767d00SRoman Moravcik unsigned int type = button->type ?: EV_KEY; 3645feeca3cSGeert Uytterhoeven int state; 36584767d00SRoman Moravcik 3665feeca3cSGeert Uytterhoeven state = gpiod_get_value_cansleep(bdata->gpiod); 36777fa0554SBjorn Andersson if (state < 0) { 3685feeca3cSGeert Uytterhoeven dev_err(input->dev.parent, 3695feeca3cSGeert Uytterhoeven "failed to get gpio state: %d\n", state); 37077fa0554SBjorn Andersson return; 37177fa0554SBjorn Andersson } 37277fa0554SBjorn Andersson 37392a47674SAlexander Stein if (type == EV_ABS) { 37492a47674SAlexander Stein if (state) 37592a47674SAlexander Stein input_event(input, type, button->code, button->value); 37692a47674SAlexander Stein } else { 377*83e4947aSHans de Goede input_event(input, type, *bdata->code, state); 37892a47674SAlexander Stein } 37978a56aabSPhil Blundell input_sync(input); 380a33466e3SDmitry Baryshkov } 381a33466e3SDmitry Baryshkov 382d8ee4a1cSLaxman Dewangan static void gpio_keys_gpio_work_func(struct work_struct *work) 3836ee88d71SDaniel Mack { 3846ee88d71SDaniel Mack struct gpio_button_data *bdata = 3858ed92556SDmitry Torokhov container_of(work, struct gpio_button_data, work.work); 3866ee88d71SDaniel Mack 387d8ee4a1cSLaxman Dewangan gpio_keys_gpio_report_event(bdata); 3882fba26c6SNeilBrown 3892fba26c6SNeilBrown if (bdata->button->wakeup) 3902fba26c6SNeilBrown pm_relax(bdata->input->dev.parent); 3916ee88d71SDaniel Mack } 3926ee88d71SDaniel Mack 393d8ee4a1cSLaxman Dewangan static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) 394a33466e3SDmitry Baryshkov { 39557ffe9d5SUwe Kleine-König struct gpio_button_data *bdata = dev_id; 396a33466e3SDmitry Baryshkov 397d8ee4a1cSLaxman Dewangan BUG_ON(irq != bdata->irq); 398a33466e3SDmitry Baryshkov 3992fba26c6SNeilBrown if (bdata->button->wakeup) 4002fba26c6SNeilBrown pm_stay_awake(bdata->input->dev.parent); 4018ed92556SDmitry Torokhov 4028ed92556SDmitry Torokhov mod_delayed_work(system_wq, 4038ed92556SDmitry Torokhov &bdata->work, 4048ed92556SDmitry Torokhov msecs_to_jiffies(bdata->software_debounce)); 405a33466e3SDmitry Baryshkov 4061164ec1aSDavid Brownell return IRQ_HANDLED; 40778a56aabSPhil Blundell } 40878a56aabSPhil Blundell 409d8ee4a1cSLaxman Dewangan static void gpio_keys_irq_timer(unsigned long _data) 410d8ee4a1cSLaxman Dewangan { 411d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = (struct gpio_button_data *)_data; 412d8ee4a1cSLaxman Dewangan struct input_dev *input = bdata->input; 413d8ee4a1cSLaxman Dewangan unsigned long flags; 414d8ee4a1cSLaxman Dewangan 415d8ee4a1cSLaxman Dewangan spin_lock_irqsave(&bdata->lock, flags); 416d8ee4a1cSLaxman Dewangan if (bdata->key_pressed) { 417*83e4947aSHans de Goede input_event(input, EV_KEY, *bdata->code, 0); 418d8ee4a1cSLaxman Dewangan input_sync(input); 419d8ee4a1cSLaxman Dewangan bdata->key_pressed = false; 420d8ee4a1cSLaxman Dewangan } 421d8ee4a1cSLaxman Dewangan spin_unlock_irqrestore(&bdata->lock, flags); 422d8ee4a1cSLaxman Dewangan } 423d8ee4a1cSLaxman Dewangan 424d8ee4a1cSLaxman Dewangan static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) 425d8ee4a1cSLaxman Dewangan { 426d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = dev_id; 427d8ee4a1cSLaxman Dewangan struct input_dev *input = bdata->input; 428d8ee4a1cSLaxman Dewangan unsigned long flags; 429d8ee4a1cSLaxman Dewangan 430d8ee4a1cSLaxman Dewangan BUG_ON(irq != bdata->irq); 431d8ee4a1cSLaxman Dewangan 432d8ee4a1cSLaxman Dewangan spin_lock_irqsave(&bdata->lock, flags); 433d8ee4a1cSLaxman Dewangan 434d8ee4a1cSLaxman Dewangan if (!bdata->key_pressed) { 4352fba26c6SNeilBrown if (bdata->button->wakeup) 4362fba26c6SNeilBrown pm_wakeup_event(bdata->input->dev.parent, 0); 4372fba26c6SNeilBrown 438*83e4947aSHans de Goede input_event(input, EV_KEY, *bdata->code, 1); 439d8ee4a1cSLaxman Dewangan input_sync(input); 440d8ee4a1cSLaxman Dewangan 4418ed92556SDmitry Torokhov if (!bdata->release_delay) { 442*83e4947aSHans de Goede input_event(input, EV_KEY, *bdata->code, 0); 443d8ee4a1cSLaxman Dewangan input_sync(input); 444d8ee4a1cSLaxman Dewangan goto out; 445d8ee4a1cSLaxman Dewangan } 446d8ee4a1cSLaxman Dewangan 447d8ee4a1cSLaxman Dewangan bdata->key_pressed = true; 448d8ee4a1cSLaxman Dewangan } 449d8ee4a1cSLaxman Dewangan 4508ed92556SDmitry Torokhov if (bdata->release_delay) 4518ed92556SDmitry Torokhov mod_timer(&bdata->release_timer, 4528ed92556SDmitry Torokhov jiffies + msecs_to_jiffies(bdata->release_delay)); 453d8ee4a1cSLaxman Dewangan out: 454d8ee4a1cSLaxman Dewangan spin_unlock_irqrestore(&bdata->lock, flags); 455d8ee4a1cSLaxman Dewangan return IRQ_HANDLED; 456d8ee4a1cSLaxman Dewangan } 457d8ee4a1cSLaxman Dewangan 45827245519SAlexander Shiyan static void gpio_keys_quiesce_key(void *data) 45927245519SAlexander Shiyan { 46027245519SAlexander Shiyan struct gpio_button_data *bdata = data; 46127245519SAlexander Shiyan 4625feeca3cSGeert Uytterhoeven if (bdata->gpiod) 4638ed92556SDmitry Torokhov cancel_delayed_work_sync(&bdata->work); 4648ed92556SDmitry Torokhov else 4658ed92556SDmitry Torokhov del_timer_sync(&bdata->release_timer); 46627245519SAlexander Shiyan } 46727245519SAlexander Shiyan 4685298cc4cSBill Pemberton static int gpio_keys_setup_key(struct platform_device *pdev, 469d9080921SDmitry Torokhov struct input_dev *input, 470*83e4947aSHans de Goede struct gpio_keys_drvdata *ddata, 471700a38b2SDmitry Torokhov const struct gpio_keys_button *button, 472*83e4947aSHans de Goede int idx, 473700a38b2SDmitry Torokhov struct fwnode_handle *child) 474bc8f1eafSBen Dooks { 47592a47674SAlexander Stein const char *desc = button->desc ? button->desc : "gpio_keys"; 4769e3af04fSMika Westerberg struct device *dev = &pdev->dev; 477*83e4947aSHans de Goede struct gpio_button_data *bdata = &ddata->data[idx]; 478d8ee4a1cSLaxman Dewangan irq_handler_t isr; 4799e3af04fSMika Westerberg unsigned long irqflags; 48027245519SAlexander Shiyan int irq; 48127245519SAlexander Shiyan int error; 482bc8f1eafSBen Dooks 483d9080921SDmitry Torokhov bdata->input = input; 484d9080921SDmitry Torokhov bdata->button = button; 485d8ee4a1cSLaxman Dewangan spin_lock_init(&bdata->lock); 486d8ee4a1cSLaxman Dewangan 487700a38b2SDmitry Torokhov if (child) { 488700a38b2SDmitry Torokhov bdata->gpiod = devm_get_gpiod_from_child(dev, NULL, child); 489700a38b2SDmitry Torokhov if (IS_ERR(bdata->gpiod)) { 490700a38b2SDmitry Torokhov error = PTR_ERR(bdata->gpiod); 491700a38b2SDmitry Torokhov if (error == -ENOENT) { 492700a38b2SDmitry Torokhov /* 493700a38b2SDmitry Torokhov * GPIO is optional, we may be dealing with 494700a38b2SDmitry Torokhov * purely interrupt-driven setup. 495700a38b2SDmitry Torokhov */ 496700a38b2SDmitry Torokhov bdata->gpiod = NULL; 497700a38b2SDmitry Torokhov } else { 498700a38b2SDmitry Torokhov if (error != -EPROBE_DEFER) 499700a38b2SDmitry Torokhov dev_err(dev, "failed to get gpio: %d\n", 500700a38b2SDmitry Torokhov error); 501700a38b2SDmitry Torokhov return error; 502700a38b2SDmitry Torokhov } 503dadbb0aaSSudeep Holla } else { 504dadbb0aaSSudeep Holla error = gpiod_direction_input(bdata->gpiod); 505dadbb0aaSSudeep Holla if (error) { 506dadbb0aaSSudeep Holla dev_err(dev, "Failed to configure GPIO %d as input: %d\n", 507dadbb0aaSSudeep Holla desc_to_gpio(bdata->gpiod), error); 508dadbb0aaSSudeep Holla return error; 509dadbb0aaSSudeep Holla } 510700a38b2SDmitry Torokhov } 511700a38b2SDmitry Torokhov } else if (gpio_is_valid(button->gpio)) { 5125feeca3cSGeert Uytterhoeven /* 5135feeca3cSGeert Uytterhoeven * Legacy GPIO number, so request the GPIO here and 5145feeca3cSGeert Uytterhoeven * convert it to descriptor. 5155feeca3cSGeert Uytterhoeven */ 5165feeca3cSGeert Uytterhoeven unsigned flags = GPIOF_IN; 517bc8f1eafSBen Dooks 5185feeca3cSGeert Uytterhoeven if (button->active_low) 5195feeca3cSGeert Uytterhoeven flags |= GPIOF_ACTIVE_LOW; 5205feeca3cSGeert Uytterhoeven 5215feeca3cSGeert Uytterhoeven error = devm_gpio_request_one(&pdev->dev, button->gpio, flags, 5225feeca3cSGeert Uytterhoeven desc); 523bc8f1eafSBen Dooks if (error < 0) { 524d8ee4a1cSLaxman Dewangan dev_err(dev, "Failed to request GPIO %d, error %d\n", 525bc8f1eafSBen Dooks button->gpio, error); 526d8ee4a1cSLaxman Dewangan return error; 527bc8f1eafSBen Dooks } 528bc8f1eafSBen Dooks 5295feeca3cSGeert Uytterhoeven bdata->gpiod = gpio_to_desc(button->gpio); 5305feeca3cSGeert Uytterhoeven if (!bdata->gpiod) 5315feeca3cSGeert Uytterhoeven return -EINVAL; 532700a38b2SDmitry Torokhov } 5335feeca3cSGeert Uytterhoeven 534700a38b2SDmitry Torokhov if (bdata->gpiod) { 53528ed684fSGrazvydas Ignotas if (button->debounce_interval) { 5365feeca3cSGeert Uytterhoeven error = gpiod_set_debounce(bdata->gpiod, 53728ed684fSGrazvydas Ignotas button->debounce_interval * 1000); 53828ed684fSGrazvydas Ignotas /* use timer if gpiolib doesn't provide debounce */ 53928ed684fSGrazvydas Ignotas if (error < 0) 5408ed92556SDmitry Torokhov bdata->software_debounce = 541d8ee4a1cSLaxman Dewangan button->debounce_interval; 54228ed684fSGrazvydas Ignotas } 54328ed684fSGrazvydas Ignotas 54497d86e07SDmitry Torokhov if (button->irq) { 54597d86e07SDmitry Torokhov bdata->irq = button->irq; 54697d86e07SDmitry Torokhov } else { 5475feeca3cSGeert Uytterhoeven irq = gpiod_to_irq(bdata->gpiod); 548bc8f1eafSBen Dooks if (irq < 0) { 549bc8f1eafSBen Dooks error = irq; 550d8ee4a1cSLaxman Dewangan dev_err(dev, 551d8ee4a1cSLaxman Dewangan "Unable to get irq number for GPIO %d, error %d\n", 552bc8f1eafSBen Dooks button->gpio, error); 55327245519SAlexander Shiyan return error; 554d8ee4a1cSLaxman Dewangan } 555d8ee4a1cSLaxman Dewangan bdata->irq = irq; 55697d86e07SDmitry Torokhov } 557d8ee4a1cSLaxman Dewangan 5588ed92556SDmitry Torokhov INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); 559d8ee4a1cSLaxman Dewangan 560d8ee4a1cSLaxman Dewangan isr = gpio_keys_gpio_isr; 561d8ee4a1cSLaxman Dewangan irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; 562d8ee4a1cSLaxman Dewangan 563d8ee4a1cSLaxman Dewangan } else { 564d8ee4a1cSLaxman Dewangan if (!button->irq) { 565700a38b2SDmitry Torokhov dev_err(dev, "Found button without gpio or irq\n"); 566d8ee4a1cSLaxman Dewangan return -EINVAL; 567d8ee4a1cSLaxman Dewangan } 568700a38b2SDmitry Torokhov 569d8ee4a1cSLaxman Dewangan bdata->irq = button->irq; 570d8ee4a1cSLaxman Dewangan 571d8ee4a1cSLaxman Dewangan if (button->type && button->type != EV_KEY) { 572d8ee4a1cSLaxman Dewangan dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); 573d8ee4a1cSLaxman Dewangan return -EINVAL; 574bc8f1eafSBen Dooks } 575bc8f1eafSBen Dooks 5768ed92556SDmitry Torokhov bdata->release_delay = button->debounce_interval; 5778ed92556SDmitry Torokhov setup_timer(&bdata->release_timer, 578d8ee4a1cSLaxman Dewangan gpio_keys_irq_timer, (unsigned long)bdata); 579d8ee4a1cSLaxman Dewangan 580d8ee4a1cSLaxman Dewangan isr = gpio_keys_irq_isr; 581d8ee4a1cSLaxman Dewangan irqflags = 0; 582d8ee4a1cSLaxman Dewangan } 583d8ee4a1cSLaxman Dewangan 584*83e4947aSHans de Goede bdata->code = &ddata->keymap[idx]; 585*83e4947aSHans de Goede *bdata->code = button->code; 586*83e4947aSHans de Goede input_set_capability(input, button->type ?: EV_KEY, *bdata->code); 587d8ee4a1cSLaxman Dewangan 5889e3af04fSMika Westerberg /* 5898ed92556SDmitry Torokhov * Install custom action to cancel release timer and 59027245519SAlexander Shiyan * workqueue item. 59127245519SAlexander Shiyan */ 59227245519SAlexander Shiyan error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); 59327245519SAlexander Shiyan if (error) { 59427245519SAlexander Shiyan dev_err(&pdev->dev, 59527245519SAlexander Shiyan "failed to register quiesce action, error: %d\n", 59627245519SAlexander Shiyan error); 59727245519SAlexander Shiyan return error; 59827245519SAlexander Shiyan } 59927245519SAlexander Shiyan 60027245519SAlexander Shiyan /* 6019e3af04fSMika Westerberg * If platform has specified that the button can be disabled, 6029e3af04fSMika Westerberg * we don't want it to share the interrupt line. 6039e3af04fSMika Westerberg */ 6049e3af04fSMika Westerberg if (!button->can_disable) 6059e3af04fSMika Westerberg irqflags |= IRQF_SHARED; 6069e3af04fSMika Westerberg 60727245519SAlexander Shiyan error = devm_request_any_context_irq(&pdev->dev, bdata->irq, 60827245519SAlexander Shiyan isr, irqflags, desc, bdata); 60994a8cab8SPhilippe Langlais if (error < 0) { 610bc8f1eafSBen Dooks dev_err(dev, "Unable to claim irq %d; error %d\n", 611d8ee4a1cSLaxman Dewangan bdata->irq, error); 61227245519SAlexander Shiyan return error; 613bc8f1eafSBen Dooks } 614bc8f1eafSBen Dooks 615bc8f1eafSBen Dooks return 0; 616bc8f1eafSBen Dooks } 617bc8f1eafSBen Dooks 6185b76d7b4SDmitry Torokhov static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) 6195b76d7b4SDmitry Torokhov { 6205b76d7b4SDmitry Torokhov struct input_dev *input = ddata->input; 6215b76d7b4SDmitry Torokhov int i; 6225b76d7b4SDmitry Torokhov 6235b76d7b4SDmitry Torokhov for (i = 0; i < ddata->pdata->nbuttons; i++) { 6245b76d7b4SDmitry Torokhov struct gpio_button_data *bdata = &ddata->data[i]; 6255feeca3cSGeert Uytterhoeven if (bdata->gpiod) 6265b76d7b4SDmitry Torokhov gpio_keys_gpio_report_event(bdata); 6275b76d7b4SDmitry Torokhov } 6285b76d7b4SDmitry Torokhov input_sync(input); 6295b76d7b4SDmitry Torokhov } 6305b76d7b4SDmitry Torokhov 631173bdd74SShubhrajyoti D static int gpio_keys_open(struct input_dev *input) 632173bdd74SShubhrajyoti D { 633173bdd74SShubhrajyoti D struct gpio_keys_drvdata *ddata = input_get_drvdata(input); 634219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = ddata->pdata; 6355b76d7b4SDmitry Torokhov int error; 636173bdd74SShubhrajyoti D 6375b76d7b4SDmitry Torokhov if (pdata->enable) { 6385b76d7b4SDmitry Torokhov error = pdata->enable(input->dev.parent); 6395b76d7b4SDmitry Torokhov if (error) 6405b76d7b4SDmitry Torokhov return error; 6415b76d7b4SDmitry Torokhov } 6425b76d7b4SDmitry Torokhov 6435b76d7b4SDmitry Torokhov /* Report current state of buttons that are connected to GPIOs */ 6445b76d7b4SDmitry Torokhov gpio_keys_report_state(ddata); 6455b76d7b4SDmitry Torokhov 6465b76d7b4SDmitry Torokhov return 0; 647173bdd74SShubhrajyoti D } 648173bdd74SShubhrajyoti D 649173bdd74SShubhrajyoti D static void gpio_keys_close(struct input_dev *input) 650173bdd74SShubhrajyoti D { 651173bdd74SShubhrajyoti D struct gpio_keys_drvdata *ddata = input_get_drvdata(input); 652219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = ddata->pdata; 653173bdd74SShubhrajyoti D 654219edc71SAlexandre Pereira da Silva if (pdata->disable) 655219edc71SAlexandre Pereira da Silva pdata->disable(input->dev.parent); 656173bdd74SShubhrajyoti D } 657173bdd74SShubhrajyoti D 658fd05d089SDavid Jander /* 659fd05d089SDavid Jander * Handlers for alternative sources of platform_data 660fd05d089SDavid Jander */ 661219edc71SAlexandre Pereira da Silva 662fd05d089SDavid Jander /* 663700a38b2SDmitry Torokhov * Translate properties into platform_data 664fd05d089SDavid Jander */ 6655298cc4cSBill Pemberton static struct gpio_keys_platform_data * 666219edc71SAlexandre Pereira da Silva gpio_keys_get_devtree_pdata(struct device *dev) 667fd05d089SDavid Jander { 668219edc71SAlexandre Pereira da Silva struct gpio_keys_platform_data *pdata; 669219edc71SAlexandre Pereira da Silva struct gpio_keys_button *button; 670700a38b2SDmitry Torokhov struct fwnode_handle *child; 671219edc71SAlexandre Pereira da Silva int nbuttons; 672fd05d089SDavid Jander 673700a38b2SDmitry Torokhov nbuttons = device_get_child_node_count(dev); 6745d422f2eSAndy Shevchenko if (nbuttons == 0) 6755d422f2eSAndy Shevchenko return ERR_PTR(-ENODEV); 676219edc71SAlexandre Pereira da Silva 6775d422f2eSAndy Shevchenko pdata = devm_kzalloc(dev, 6785d422f2eSAndy Shevchenko sizeof(*pdata) + nbuttons * sizeof(*button), 679219edc71SAlexandre Pereira da Silva GFP_KERNEL); 6805d422f2eSAndy Shevchenko if (!pdata) 6815d422f2eSAndy Shevchenko return ERR_PTR(-ENOMEM); 682219edc71SAlexandre Pereira da Silva 6830f78ba96SDmitry Torokhov button = (struct gpio_keys_button *)(pdata + 1); 6840f78ba96SDmitry Torokhov 6850f78ba96SDmitry Torokhov pdata->buttons = button; 686219edc71SAlexandre Pereira da Silva pdata->nbuttons = nbuttons; 687fd05d089SDavid Jander 688700a38b2SDmitry Torokhov pdata->rep = device_property_read_bool(dev, "autorepeat"); 689fd05d089SDavid Jander 690700a38b2SDmitry Torokhov device_property_read_string(dev, "label", &pdata->name); 691c4dc5f8cSLaxman Dewangan 692700a38b2SDmitry Torokhov device_for_each_child_node(dev, child) { 693700a38b2SDmitry Torokhov if (is_of_node(child)) 694700a38b2SDmitry Torokhov button->irq = 695700a38b2SDmitry Torokhov irq_of_parse_and_map(to_of_node(child), 0); 696fd05d089SDavid Jander 697700a38b2SDmitry Torokhov if (fwnode_property_read_u32(child, "linux,code", 698700a38b2SDmitry Torokhov &button->code)) { 699700a38b2SDmitry Torokhov dev_err(dev, "Button without keycode\n"); 700700a38b2SDmitry Torokhov fwnode_handle_put(child); 70197d86e07SDmitry Torokhov return ERR_PTR(-EINVAL); 70297d86e07SDmitry Torokhov } 703fd05d089SDavid Jander 704700a38b2SDmitry Torokhov fwnode_property_read_string(child, "label", &button->desc); 705fd05d089SDavid Jander 706700a38b2SDmitry Torokhov if (fwnode_property_read_u32(child, "linux,input-type", 707700a38b2SDmitry Torokhov &button->type)) 708219edc71SAlexandre Pereira da Silva button->type = EV_KEY; 709fd05d089SDavid Jander 710700a38b2SDmitry Torokhov button->wakeup = 711700a38b2SDmitry Torokhov fwnode_property_read_bool(child, "wakeup-source") || 71299b4ffbdSDmitry Torokhov /* legacy name */ 713700a38b2SDmitry Torokhov fwnode_property_read_bool(child, "gpio-key,wakeup"); 714219edc71SAlexandre Pereira da Silva 715700a38b2SDmitry Torokhov button->can_disable = 716700a38b2SDmitry Torokhov fwnode_property_read_bool(child, "linux,can-disable"); 71797d86e07SDmitry Torokhov 718700a38b2SDmitry Torokhov if (fwnode_property_read_u32(child, "debounce-interval", 719219edc71SAlexandre Pereira da Silva &button->debounce_interval)) 720219edc71SAlexandre Pereira da Silva button->debounce_interval = 5; 7210f78ba96SDmitry Torokhov 7220f78ba96SDmitry Torokhov button++; 723219edc71SAlexandre Pereira da Silva } 724219edc71SAlexandre Pereira da Silva 725219edc71SAlexandre Pereira da Silva return pdata; 726fd05d089SDavid Jander } 727fd05d089SDavid Jander 72822daae31SJingoo Han static const struct of_device_id gpio_keys_of_match[] = { 729fd05d089SDavid Jander { .compatible = "gpio-keys", }, 730fd05d089SDavid Jander { }, 731fd05d089SDavid Jander }; 732fd05d089SDavid Jander MODULE_DEVICE_TABLE(of, gpio_keys_of_match); 733fd05d089SDavid Jander 7345298cc4cSBill Pemberton static int gpio_keys_probe(struct platform_device *pdev) 73578a56aabSPhil Blundell { 736db19fd8bSBen Dooks struct device *dev = &pdev->dev; 737219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); 738700a38b2SDmitry Torokhov struct fwnode_handle *child = NULL; 739219edc71SAlexandre Pereira da Silva struct gpio_keys_drvdata *ddata; 74078a56aabSPhil Blundell struct input_dev *input; 7415d422f2eSAndy Shevchenko size_t size; 74278a56aabSPhil Blundell int i, error; 743e15b0213SAnti Sullin int wakeup = 0; 74478a56aabSPhil Blundell 745fd05d089SDavid Jander if (!pdata) { 746219edc71SAlexandre Pereira da Silva pdata = gpio_keys_get_devtree_pdata(dev); 747219edc71SAlexandre Pereira da Silva if (IS_ERR(pdata)) 748219edc71SAlexandre Pereira da Silva return PTR_ERR(pdata); 749fd05d089SDavid Jander } 750fd05d089SDavid Jander 7515d422f2eSAndy Shevchenko size = sizeof(struct gpio_keys_drvdata) + 7525d422f2eSAndy Shevchenko pdata->nbuttons * sizeof(struct gpio_button_data); 7535d422f2eSAndy Shevchenko ddata = devm_kzalloc(dev, size, GFP_KERNEL); 7545d422f2eSAndy Shevchenko if (!ddata) { 755db19fd8bSBen Dooks dev_err(dev, "failed to allocate state\n"); 7565d422f2eSAndy Shevchenko return -ENOMEM; 7575d422f2eSAndy Shevchenko } 7585d422f2eSAndy Shevchenko 759*83e4947aSHans de Goede ddata->keymap = devm_kcalloc(dev, 760*83e4947aSHans de Goede pdata->nbuttons, sizeof(ddata->keymap[0]), 761*83e4947aSHans de Goede GFP_KERNEL); 762*83e4947aSHans de Goede if (!ddata->keymap) 763*83e4947aSHans de Goede return -ENOMEM; 764*83e4947aSHans de Goede 7655d422f2eSAndy Shevchenko input = devm_input_allocate_device(dev); 7665d422f2eSAndy Shevchenko if (!input) { 7675d422f2eSAndy Shevchenko dev_err(dev, "failed to allocate input device\n"); 7685d422f2eSAndy Shevchenko return -ENOMEM; 769a33466e3SDmitry Baryshkov } 77078a56aabSPhil Blundell 771219edc71SAlexandre Pereira da Silva ddata->pdata = pdata; 7729e3af04fSMika Westerberg ddata->input = input; 7739e3af04fSMika Westerberg mutex_init(&ddata->disable_lock); 7749e3af04fSMika Westerberg 775a33466e3SDmitry Baryshkov platform_set_drvdata(pdev, ddata); 776173bdd74SShubhrajyoti D input_set_drvdata(input, ddata); 77778a56aabSPhil Blundell 77846711277SAlexander Stein input->name = pdata->name ? : pdev->name; 77978a56aabSPhil Blundell input->phys = "gpio-keys/input0"; 780469ba4dfSDmitry Torokhov input->dev.parent = &pdev->dev; 781173bdd74SShubhrajyoti D input->open = gpio_keys_open; 782173bdd74SShubhrajyoti D input->close = gpio_keys_close; 78378a56aabSPhil Blundell 78478a56aabSPhil Blundell input->id.bustype = BUS_HOST; 78578a56aabSPhil Blundell input->id.vendor = 0x0001; 78678a56aabSPhil Blundell input->id.product = 0x0001; 78778a56aabSPhil Blundell input->id.version = 0x0100; 78878a56aabSPhil Blundell 789*83e4947aSHans de Goede input->keycode = ddata->keymap; 790*83e4947aSHans de Goede input->keycodesize = sizeof(ddata->keymap[0]); 791*83e4947aSHans de Goede input->keycodemax = pdata->nbuttons; 792*83e4947aSHans de Goede 793b67b4b11SDominic Curran /* Enable auto repeat feature of Linux input subsystem */ 794b67b4b11SDominic Curran if (pdata->rep) 795b67b4b11SDominic Curran __set_bit(EV_REP, input->evbit); 796b67b4b11SDominic Curran 79778a56aabSPhil Blundell for (i = 0; i < pdata->nbuttons; i++) { 798d9080921SDmitry Torokhov const struct gpio_keys_button *button = &pdata->buttons[i]; 79978a56aabSPhil Blundell 800700a38b2SDmitry Torokhov if (!dev_get_platdata(dev)) { 801700a38b2SDmitry Torokhov child = device_get_next_child_node(&pdev->dev, child); 802700a38b2SDmitry Torokhov if (!child) { 803700a38b2SDmitry Torokhov dev_err(&pdev->dev, 804700a38b2SDmitry Torokhov "missing child device node for entry %d\n", 805700a38b2SDmitry Torokhov i); 806700a38b2SDmitry Torokhov return -EINVAL; 807700a38b2SDmitry Torokhov } 808700a38b2SDmitry Torokhov } 809700a38b2SDmitry Torokhov 810*83e4947aSHans de Goede error = gpio_keys_setup_key(pdev, input, ddata, 811*83e4947aSHans de Goede button, i, child); 812700a38b2SDmitry Torokhov if (error) { 813700a38b2SDmitry Torokhov fwnode_handle_put(child); 81427245519SAlexander Shiyan return error; 815700a38b2SDmitry Torokhov } 81684767d00SRoman Moravcik 817e15b0213SAnti Sullin if (button->wakeup) 818e15b0213SAnti Sullin wakeup = 1; 81978a56aabSPhil Blundell } 82078a56aabSPhil Blundell 821700a38b2SDmitry Torokhov fwnode_handle_put(child); 822700a38b2SDmitry Torokhov 8239e3af04fSMika Westerberg error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); 8249e3af04fSMika Westerberg if (error) { 8259e3af04fSMika Westerberg dev_err(dev, "Unable to export keys/switches, error: %d\n", 8269e3af04fSMika Westerberg error); 82727245519SAlexander Shiyan return error; 8289e3af04fSMika Westerberg } 8299e3af04fSMika Westerberg 83078a56aabSPhil Blundell error = input_register_device(input); 83178a56aabSPhil Blundell if (error) { 8329e3af04fSMika Westerberg dev_err(dev, "Unable to register input device, error: %d\n", 8339e3af04fSMika Westerberg error); 83427245519SAlexander Shiyan goto err_remove_group; 83578a56aabSPhil Blundell } 83678a56aabSPhil Blundell 837e15b0213SAnti Sullin device_init_wakeup(&pdev->dev, wakeup); 838e15b0213SAnti Sullin 83978a56aabSPhil Blundell return 0; 84078a56aabSPhil Blundell 84127245519SAlexander Shiyan err_remove_group: 8429e3af04fSMika Westerberg sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); 84378a56aabSPhil Blundell return error; 84478a56aabSPhil Blundell } 84578a56aabSPhil Blundell 846e2619cf7SBill Pemberton static int gpio_keys_remove(struct platform_device *pdev) 84778a56aabSPhil Blundell { 8489e3af04fSMika Westerberg sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); 8499e3af04fSMika Westerberg 850e15b0213SAnti Sullin device_init_wakeup(&pdev->dev, 0); 851e15b0213SAnti Sullin 85278a56aabSPhil Blundell return 0; 85378a56aabSPhil Blundell } 85478a56aabSPhil Blundell 855f9645f22SDmitry Torokhov static int __maybe_unused gpio_keys_suspend(struct device *dev) 856e15b0213SAnti Sullin { 857fd05d089SDavid Jander struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 858dda19a92SJonas Aaberg struct input_dev *input = ddata->input; 859e15b0213SAnti Sullin int i; 860e15b0213SAnti Sullin 861fd05d089SDavid Jander if (device_may_wakeup(dev)) { 862219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 863d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = &ddata->data[i]; 864d8ee4a1cSLaxman Dewangan if (bdata->button->wakeup) 865d8ee4a1cSLaxman Dewangan enable_irq_wake(bdata->irq); 866e15b0213SAnti Sullin } 867dda19a92SJonas Aaberg } else { 868dda19a92SJonas Aaberg mutex_lock(&input->mutex); 869dda19a92SJonas Aaberg if (input->users) 870dda19a92SJonas Aaberg gpio_keys_close(input); 871dda19a92SJonas Aaberg mutex_unlock(&input->mutex); 872e15b0213SAnti Sullin } 873e15b0213SAnti Sullin 874e15b0213SAnti Sullin return 0; 875e15b0213SAnti Sullin } 876e15b0213SAnti Sullin 877f9645f22SDmitry Torokhov static int __maybe_unused gpio_keys_resume(struct device *dev) 878e15b0213SAnti Sullin { 879fd05d089SDavid Jander struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 880dda19a92SJonas Aaberg struct input_dev *input = ddata->input; 881dda19a92SJonas Aaberg int error = 0; 882e15b0213SAnti Sullin int i; 883e15b0213SAnti Sullin 884dda19a92SJonas Aaberg if (device_may_wakeup(dev)) { 885219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 886d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = &ddata->data[i]; 887dda19a92SJonas Aaberg if (bdata->button->wakeup) 888d8ee4a1cSLaxman Dewangan disable_irq_wake(bdata->irq); 889e15b0213SAnti Sullin } 890dda19a92SJonas Aaberg } else { 891dda19a92SJonas Aaberg mutex_lock(&input->mutex); 892dda19a92SJonas Aaberg if (input->users) 893dda19a92SJonas Aaberg error = gpio_keys_open(input); 894dda19a92SJonas Aaberg mutex_unlock(&input->mutex); 895dda19a92SJonas Aaberg } 896dda19a92SJonas Aaberg 897dda19a92SJonas Aaberg if (error) 898dda19a92SJonas Aaberg return error; 8995b76d7b4SDmitry Torokhov 9005b76d7b4SDmitry Torokhov gpio_keys_report_state(ddata); 901e15b0213SAnti Sullin return 0; 902e15b0213SAnti Sullin } 903e15b0213SAnti Sullin 904bdda8216SDmitry Torokhov static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); 905bdda8216SDmitry Torokhov 9069b07044cSUwe Kleine-König static struct platform_driver gpio_keys_device_driver = { 90778a56aabSPhil Blundell .probe = gpio_keys_probe, 9081cb0aa88SBill Pemberton .remove = gpio_keys_remove, 90978a56aabSPhil Blundell .driver = { 91078a56aabSPhil Blundell .name = "gpio-keys", 911ae78e0e0SMike Rapoport .pm = &gpio_keys_pm_ops, 912700a38b2SDmitry Torokhov .of_match_table = gpio_keys_of_match, 91378a56aabSPhil Blundell } 91478a56aabSPhil Blundell }; 91578a56aabSPhil Blundell 91678a56aabSPhil Blundell static int __init gpio_keys_init(void) 91778a56aabSPhil Blundell { 91878a56aabSPhil Blundell return platform_driver_register(&gpio_keys_device_driver); 91978a56aabSPhil Blundell } 92078a56aabSPhil Blundell 92178a56aabSPhil Blundell static void __exit gpio_keys_exit(void) 92278a56aabSPhil Blundell { 92378a56aabSPhil Blundell platform_driver_unregister(&gpio_keys_device_driver); 92478a56aabSPhil Blundell } 92578a56aabSPhil Blundell 926b2330205SDavid Jander late_initcall(gpio_keys_init); 92778a56aabSPhil Blundell module_exit(gpio_keys_exit); 92878a56aabSPhil Blundell 92978a56aabSPhil Blundell MODULE_LICENSE("GPL"); 93078a56aabSPhil Blundell MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); 9317e2ecdf4SDavid Jander MODULE_DESCRIPTION("Keyboard driver for GPIOs"); 932d7b5247bSKay Sievers MODULE_ALIAS("platform:gpio-keys"); 933