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> 29fd05d089SDavid Jander #include <linux/of_platform.h> 30fd05d089SDavid Jander #include <linux/of_gpio.h> 31d8ee4a1cSLaxman Dewangan #include <linux/spinlock.h> 3278a56aabSPhil Blundell 33a33466e3SDmitry Baryshkov struct gpio_button_data { 34d9080921SDmitry Torokhov const struct gpio_keys_button *button; 35a33466e3SDmitry Baryshkov struct input_dev *input; 36ca865a77SJani Nikula struct timer_list timer; 37da0d03feSJani Nikula struct work_struct work; 38d8ee4a1cSLaxman Dewangan unsigned int timer_debounce; /* in msecs */ 39d8ee4a1cSLaxman Dewangan unsigned int irq; 40d8ee4a1cSLaxman Dewangan spinlock_t lock; 419e3af04fSMika Westerberg bool disabled; 42d8ee4a1cSLaxman Dewangan bool key_pressed; 43a33466e3SDmitry Baryshkov }; 44a33466e3SDmitry Baryshkov 45a33466e3SDmitry Baryshkov struct gpio_keys_drvdata { 46*219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata; 47a33466e3SDmitry Baryshkov struct input_dev *input; 489e3af04fSMika Westerberg struct mutex disable_lock; 49a33466e3SDmitry Baryshkov struct gpio_button_data data[0]; 50a33466e3SDmitry Baryshkov }; 51a33466e3SDmitry Baryshkov 529e3af04fSMika Westerberg /* 539e3af04fSMika Westerberg * SYSFS interface for enabling/disabling keys and switches: 549e3af04fSMika Westerberg * 559e3af04fSMika Westerberg * There are 4 attributes under /sys/devices/platform/gpio-keys/ 569e3af04fSMika Westerberg * keys [ro] - bitmap of keys (EV_KEY) which can be 579e3af04fSMika Westerberg * disabled 589e3af04fSMika Westerberg * switches [ro] - bitmap of switches (EV_SW) which can be 599e3af04fSMika Westerberg * disabled 609e3af04fSMika Westerberg * disabled_keys [rw] - bitmap of keys currently disabled 619e3af04fSMika Westerberg * disabled_switches [rw] - bitmap of switches currently disabled 629e3af04fSMika Westerberg * 639e3af04fSMika Westerberg * Userland can change these values and hence disable event generation 649e3af04fSMika Westerberg * for each key (or switch). Disabling a key means its interrupt line 659e3af04fSMika Westerberg * is disabled. 669e3af04fSMika Westerberg * 679e3af04fSMika Westerberg * For example, if we have following switches set up as gpio-keys: 689e3af04fSMika Westerberg * SW_DOCK = 5 699e3af04fSMika Westerberg * SW_CAMERA_LENS_COVER = 9 709e3af04fSMika Westerberg * SW_KEYPAD_SLIDE = 10 719e3af04fSMika Westerberg * SW_FRONT_PROXIMITY = 11 729e3af04fSMika Westerberg * This is read from switches: 739e3af04fSMika Westerberg * 11-9,5 749e3af04fSMika Westerberg * Next we want to disable proximity (11) and dock (5), we write: 759e3af04fSMika Westerberg * 11,5 769e3af04fSMika Westerberg * to file disabled_switches. Now proximity and dock IRQs are disabled. 779e3af04fSMika Westerberg * This can be verified by reading the file disabled_switches: 789e3af04fSMika Westerberg * 11,5 799e3af04fSMika Westerberg * If we now want to enable proximity (11) switch we write: 809e3af04fSMika Westerberg * 5 819e3af04fSMika Westerberg * to disabled_switches. 829e3af04fSMika Westerberg * 839e3af04fSMika Westerberg * We can disable only those keys which don't allow sharing the irq. 849e3af04fSMika Westerberg */ 859e3af04fSMika Westerberg 869e3af04fSMika Westerberg /** 879e3af04fSMika Westerberg * get_n_events_by_type() - returns maximum number of events per @type 889e3af04fSMika Westerberg * @type: type of button (%EV_KEY, %EV_SW) 899e3af04fSMika Westerberg * 909e3af04fSMika Westerberg * Return value of this function can be used to allocate bitmap 919e3af04fSMika Westerberg * large enough to hold all bits for given type. 929e3af04fSMika Westerberg */ 939e3af04fSMika Westerberg static inline int get_n_events_by_type(int type) 949e3af04fSMika Westerberg { 959e3af04fSMika Westerberg BUG_ON(type != EV_SW && type != EV_KEY); 969e3af04fSMika Westerberg 979e3af04fSMika Westerberg return (type == EV_KEY) ? KEY_CNT : SW_CNT; 989e3af04fSMika Westerberg } 999e3af04fSMika Westerberg 1009e3af04fSMika Westerberg /** 1019e3af04fSMika Westerberg * gpio_keys_disable_button() - disables given GPIO button 1029e3af04fSMika Westerberg * @bdata: button data for button to be disabled 1039e3af04fSMika Westerberg * 1049e3af04fSMika Westerberg * Disables button pointed by @bdata. This is done by masking 1059e3af04fSMika Westerberg * IRQ line. After this function is called, button won't generate 1069e3af04fSMika Westerberg * input events anymore. Note that one can only disable buttons 1079e3af04fSMika Westerberg * that don't share IRQs. 1089e3af04fSMika Westerberg * 1099e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1109e3af04fSMika Westerberg * this function to avoid races when concurrent threads are 1119e3af04fSMika Westerberg * disabling buttons at the same time. 1129e3af04fSMika Westerberg */ 1139e3af04fSMika Westerberg static void gpio_keys_disable_button(struct gpio_button_data *bdata) 1149e3af04fSMika Westerberg { 1159e3af04fSMika Westerberg if (!bdata->disabled) { 1169e3af04fSMika Westerberg /* 1179e3af04fSMika Westerberg * Disable IRQ and possible debouncing timer. 1189e3af04fSMika Westerberg */ 119d8ee4a1cSLaxman Dewangan disable_irq(bdata->irq); 12028ed684fSGrazvydas Ignotas if (bdata->timer_debounce) 1219e3af04fSMika Westerberg del_timer_sync(&bdata->timer); 1229e3af04fSMika Westerberg 1239e3af04fSMika Westerberg bdata->disabled = true; 1249e3af04fSMika Westerberg } 1259e3af04fSMika Westerberg } 1269e3af04fSMika Westerberg 1279e3af04fSMika Westerberg /** 1289e3af04fSMika Westerberg * gpio_keys_enable_button() - enables given GPIO button 1299e3af04fSMika Westerberg * @bdata: button data for button to be disabled 1309e3af04fSMika Westerberg * 1319e3af04fSMika Westerberg * Enables given button pointed by @bdata. 1329e3af04fSMika Westerberg * 1339e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1349e3af04fSMika Westerberg * this function to avoid races with concurrent threads trying 1359e3af04fSMika Westerberg * to enable the same button at the same time. 1369e3af04fSMika Westerberg */ 1379e3af04fSMika Westerberg static void gpio_keys_enable_button(struct gpio_button_data *bdata) 1389e3af04fSMika Westerberg { 1399e3af04fSMika Westerberg if (bdata->disabled) { 140d8ee4a1cSLaxman Dewangan enable_irq(bdata->irq); 1419e3af04fSMika Westerberg bdata->disabled = false; 1429e3af04fSMika Westerberg } 1439e3af04fSMika Westerberg } 1449e3af04fSMika Westerberg 1459e3af04fSMika Westerberg /** 1469e3af04fSMika Westerberg * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons 1479e3af04fSMika Westerberg * @ddata: pointer to drvdata 1489e3af04fSMika Westerberg * @buf: buffer where stringified bitmap is written 1499e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 1509e3af04fSMika Westerberg * @only_disabled: does caller want only those buttons that are 1519e3af04fSMika Westerberg * currently disabled or all buttons that can be 1529e3af04fSMika Westerberg * disabled 1539e3af04fSMika Westerberg * 1549e3af04fSMika Westerberg * This function writes buttons that can be disabled to @buf. If 1559e3af04fSMika Westerberg * @only_disabled is true, then @buf contains only those buttons 1569e3af04fSMika Westerberg * that are currently disabled. Returns 0 on success or negative 1579e3af04fSMika Westerberg * errno on failure. 1589e3af04fSMika Westerberg */ 1599e3af04fSMika Westerberg static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, 1609e3af04fSMika Westerberg char *buf, unsigned int type, 1619e3af04fSMika Westerberg bool only_disabled) 1629e3af04fSMika Westerberg { 1639e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 1649e3af04fSMika Westerberg unsigned long *bits; 1659e3af04fSMika Westerberg ssize_t ret; 1669e3af04fSMika Westerberg int i; 1679e3af04fSMika Westerberg 1689e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 1699e3af04fSMika Westerberg if (!bits) 1709e3af04fSMika Westerberg return -ENOMEM; 1719e3af04fSMika Westerberg 172*219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 1739e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 1749e3af04fSMika Westerberg 1759e3af04fSMika Westerberg if (bdata->button->type != type) 1769e3af04fSMika Westerberg continue; 1779e3af04fSMika Westerberg 1789e3af04fSMika Westerberg if (only_disabled && !bdata->disabled) 1799e3af04fSMika Westerberg continue; 1809e3af04fSMika Westerberg 1819e3af04fSMika Westerberg __set_bit(bdata->button->code, bits); 1829e3af04fSMika Westerberg } 1839e3af04fSMika Westerberg 1849e3af04fSMika Westerberg ret = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, bits, n_events); 1859e3af04fSMika Westerberg buf[ret++] = '\n'; 1869e3af04fSMika Westerberg buf[ret] = '\0'; 1879e3af04fSMika Westerberg 1889e3af04fSMika Westerberg kfree(bits); 1899e3af04fSMika Westerberg 1909e3af04fSMika Westerberg return ret; 1919e3af04fSMika Westerberg } 1929e3af04fSMika Westerberg 1939e3af04fSMika Westerberg /** 1949e3af04fSMika Westerberg * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap 1959e3af04fSMika Westerberg * @ddata: pointer to drvdata 1969e3af04fSMika Westerberg * @buf: buffer from userspace that contains stringified bitmap 1979e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 1989e3af04fSMika Westerberg * 1999e3af04fSMika Westerberg * This function parses stringified bitmap from @buf and disables/enables 200a16ca239SDmitry Torokhov * GPIO buttons accordingly. Returns 0 on success and negative error 2019e3af04fSMika Westerberg * on failure. 2029e3af04fSMika Westerberg */ 2039e3af04fSMika Westerberg static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, 2049e3af04fSMika Westerberg const char *buf, unsigned int type) 2059e3af04fSMika Westerberg { 2069e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 2079e3af04fSMika Westerberg unsigned long *bits; 2089e3af04fSMika Westerberg ssize_t error; 2099e3af04fSMika Westerberg int i; 2109e3af04fSMika Westerberg 2119e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 2129e3af04fSMika Westerberg if (!bits) 2139e3af04fSMika Westerberg return -ENOMEM; 2149e3af04fSMika Westerberg 2159e3af04fSMika Westerberg error = bitmap_parselist(buf, bits, n_events); 2169e3af04fSMika Westerberg if (error) 2179e3af04fSMika Westerberg goto out; 2189e3af04fSMika Westerberg 2199e3af04fSMika Westerberg /* First validate */ 220*219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2219e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2229e3af04fSMika Westerberg 2239e3af04fSMika Westerberg if (bdata->button->type != type) 2249e3af04fSMika Westerberg continue; 2259e3af04fSMika Westerberg 2269e3af04fSMika Westerberg if (test_bit(bdata->button->code, bits) && 2279e3af04fSMika Westerberg !bdata->button->can_disable) { 2289e3af04fSMika Westerberg error = -EINVAL; 2299e3af04fSMika Westerberg goto out; 2309e3af04fSMika Westerberg } 2319e3af04fSMika Westerberg } 2329e3af04fSMika Westerberg 2339e3af04fSMika Westerberg mutex_lock(&ddata->disable_lock); 2349e3af04fSMika Westerberg 235*219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 2369e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2379e3af04fSMika Westerberg 2389e3af04fSMika Westerberg if (bdata->button->type != type) 2399e3af04fSMika Westerberg continue; 2409e3af04fSMika Westerberg 2419e3af04fSMika Westerberg if (test_bit(bdata->button->code, bits)) 2429e3af04fSMika Westerberg gpio_keys_disable_button(bdata); 2439e3af04fSMika Westerberg else 2449e3af04fSMika Westerberg gpio_keys_enable_button(bdata); 2459e3af04fSMika Westerberg } 2469e3af04fSMika Westerberg 2479e3af04fSMika Westerberg mutex_unlock(&ddata->disable_lock); 2489e3af04fSMika Westerberg 2499e3af04fSMika Westerberg out: 2509e3af04fSMika Westerberg kfree(bits); 2519e3af04fSMika Westerberg return error; 2529e3af04fSMika Westerberg } 2539e3af04fSMika Westerberg 2549e3af04fSMika Westerberg #define ATTR_SHOW_FN(name, type, only_disabled) \ 2559e3af04fSMika Westerberg static ssize_t gpio_keys_show_##name(struct device *dev, \ 2569e3af04fSMika Westerberg struct device_attribute *attr, \ 2579e3af04fSMika Westerberg char *buf) \ 2589e3af04fSMika Westerberg { \ 2599e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 2609e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 2619e3af04fSMika Westerberg \ 2629e3af04fSMika Westerberg return gpio_keys_attr_show_helper(ddata, buf, \ 2639e3af04fSMika Westerberg type, only_disabled); \ 2649e3af04fSMika Westerberg } 2659e3af04fSMika Westerberg 2669e3af04fSMika Westerberg ATTR_SHOW_FN(keys, EV_KEY, false); 2679e3af04fSMika Westerberg ATTR_SHOW_FN(switches, EV_SW, false); 2689e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_keys, EV_KEY, true); 2699e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_switches, EV_SW, true); 2709e3af04fSMika Westerberg 2719e3af04fSMika Westerberg /* 2729e3af04fSMika Westerberg * ATTRIBUTES: 2739e3af04fSMika Westerberg * 2749e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/keys [ro] 2759e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/switches [ro] 2769e3af04fSMika Westerberg */ 2779e3af04fSMika Westerberg static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL); 2789e3af04fSMika Westerberg static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL); 2799e3af04fSMika Westerberg 2809e3af04fSMika Westerberg #define ATTR_STORE_FN(name, type) \ 2819e3af04fSMika Westerberg static ssize_t gpio_keys_store_##name(struct device *dev, \ 2829e3af04fSMika Westerberg struct device_attribute *attr, \ 2839e3af04fSMika Westerberg const char *buf, \ 2849e3af04fSMika Westerberg size_t count) \ 2859e3af04fSMika Westerberg { \ 2869e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 2879e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 2889e3af04fSMika Westerberg ssize_t error; \ 2899e3af04fSMika Westerberg \ 2909e3af04fSMika Westerberg error = gpio_keys_attr_store_helper(ddata, buf, type); \ 2919e3af04fSMika Westerberg if (error) \ 2929e3af04fSMika Westerberg return error; \ 2939e3af04fSMika Westerberg \ 2949e3af04fSMika Westerberg return count; \ 2959e3af04fSMika Westerberg } 2969e3af04fSMika Westerberg 2979e3af04fSMika Westerberg ATTR_STORE_FN(disabled_keys, EV_KEY); 2989e3af04fSMika Westerberg ATTR_STORE_FN(disabled_switches, EV_SW); 2999e3af04fSMika Westerberg 3009e3af04fSMika Westerberg /* 3019e3af04fSMika Westerberg * ATTRIBUTES: 3029e3af04fSMika Westerberg * 3039e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disabled_keys [rw] 3049e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disables_switches [rw] 3059e3af04fSMika Westerberg */ 3069e3af04fSMika Westerberg static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO, 3079e3af04fSMika Westerberg gpio_keys_show_disabled_keys, 3089e3af04fSMika Westerberg gpio_keys_store_disabled_keys); 3099e3af04fSMika Westerberg static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO, 3109e3af04fSMika Westerberg gpio_keys_show_disabled_switches, 3119e3af04fSMika Westerberg gpio_keys_store_disabled_switches); 3129e3af04fSMika Westerberg 3139e3af04fSMika Westerberg static struct attribute *gpio_keys_attrs[] = { 3149e3af04fSMika Westerberg &dev_attr_keys.attr, 3159e3af04fSMika Westerberg &dev_attr_switches.attr, 3169e3af04fSMika Westerberg &dev_attr_disabled_keys.attr, 3179e3af04fSMika Westerberg &dev_attr_disabled_switches.attr, 3189e3af04fSMika Westerberg NULL, 3199e3af04fSMika Westerberg }; 3209e3af04fSMika Westerberg 3219e3af04fSMika Westerberg static struct attribute_group gpio_keys_attr_group = { 3229e3af04fSMika Westerberg .attrs = gpio_keys_attrs, 3239e3af04fSMika Westerberg }; 3249e3af04fSMika Westerberg 325d8ee4a1cSLaxman Dewangan static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) 32678a56aabSPhil Blundell { 327d9080921SDmitry Torokhov const struct gpio_keys_button *button = bdata->button; 328ce25d7e9SUwe Kleine-König struct input_dev *input = bdata->input; 32984767d00SRoman Moravcik unsigned int type = button->type ?: EV_KEY; 33094a8cab8SPhilippe Langlais int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; 33184767d00SRoman Moravcik 33292a47674SAlexander Stein if (type == EV_ABS) { 33392a47674SAlexander Stein if (state) 33492a47674SAlexander Stein input_event(input, type, button->code, button->value); 33592a47674SAlexander Stein } else { 33684767d00SRoman Moravcik input_event(input, type, button->code, !!state); 33792a47674SAlexander Stein } 33878a56aabSPhil Blundell input_sync(input); 339a33466e3SDmitry Baryshkov } 340a33466e3SDmitry Baryshkov 341d8ee4a1cSLaxman Dewangan static void gpio_keys_gpio_work_func(struct work_struct *work) 3426ee88d71SDaniel Mack { 3436ee88d71SDaniel Mack struct gpio_button_data *bdata = 3446ee88d71SDaniel Mack container_of(work, struct gpio_button_data, work); 3456ee88d71SDaniel Mack 346d8ee4a1cSLaxman Dewangan gpio_keys_gpio_report_event(bdata); 3476ee88d71SDaniel Mack } 3486ee88d71SDaniel Mack 349d8ee4a1cSLaxman Dewangan static void gpio_keys_gpio_timer(unsigned long _data) 350ca865a77SJani Nikula { 351d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = (struct gpio_button_data *)_data; 352ca865a77SJani Nikula 353d8ee4a1cSLaxman Dewangan schedule_work(&bdata->work); 354ca865a77SJani Nikula } 355ca865a77SJani Nikula 356d8ee4a1cSLaxman Dewangan static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) 357a33466e3SDmitry Baryshkov { 35857ffe9d5SUwe Kleine-König struct gpio_button_data *bdata = dev_id; 359a33466e3SDmitry Baryshkov 360d8ee4a1cSLaxman Dewangan BUG_ON(irq != bdata->irq); 361a33466e3SDmitry Baryshkov 36228ed684fSGrazvydas Ignotas if (bdata->timer_debounce) 363ca865a77SJani Nikula mod_timer(&bdata->timer, 36428ed684fSGrazvydas Ignotas jiffies + msecs_to_jiffies(bdata->timer_debounce)); 365ca865a77SJani Nikula else 366da0d03feSJani Nikula schedule_work(&bdata->work); 367a33466e3SDmitry Baryshkov 3681164ec1aSDavid Brownell return IRQ_HANDLED; 36978a56aabSPhil Blundell } 37078a56aabSPhil Blundell 371d8ee4a1cSLaxman Dewangan static void gpio_keys_irq_timer(unsigned long _data) 372d8ee4a1cSLaxman Dewangan { 373d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = (struct gpio_button_data *)_data; 374d8ee4a1cSLaxman Dewangan struct input_dev *input = bdata->input; 375d8ee4a1cSLaxman Dewangan unsigned long flags; 376d8ee4a1cSLaxman Dewangan 377d8ee4a1cSLaxman Dewangan spin_lock_irqsave(&bdata->lock, flags); 378d8ee4a1cSLaxman Dewangan if (bdata->key_pressed) { 379d8ee4a1cSLaxman Dewangan input_event(input, EV_KEY, bdata->button->code, 0); 380d8ee4a1cSLaxman Dewangan input_sync(input); 381d8ee4a1cSLaxman Dewangan bdata->key_pressed = false; 382d8ee4a1cSLaxman Dewangan } 383d8ee4a1cSLaxman Dewangan spin_unlock_irqrestore(&bdata->lock, flags); 384d8ee4a1cSLaxman Dewangan } 385d8ee4a1cSLaxman Dewangan 386d8ee4a1cSLaxman Dewangan static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) 387d8ee4a1cSLaxman Dewangan { 388d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = dev_id; 389d8ee4a1cSLaxman Dewangan const struct gpio_keys_button *button = bdata->button; 390d8ee4a1cSLaxman Dewangan struct input_dev *input = bdata->input; 391d8ee4a1cSLaxman Dewangan unsigned long flags; 392d8ee4a1cSLaxman Dewangan 393d8ee4a1cSLaxman Dewangan BUG_ON(irq != bdata->irq); 394d8ee4a1cSLaxman Dewangan 395d8ee4a1cSLaxman Dewangan spin_lock_irqsave(&bdata->lock, flags); 396d8ee4a1cSLaxman Dewangan 397d8ee4a1cSLaxman Dewangan if (!bdata->key_pressed) { 398d8ee4a1cSLaxman Dewangan input_event(input, EV_KEY, button->code, 1); 399d8ee4a1cSLaxman Dewangan input_sync(input); 400d8ee4a1cSLaxman Dewangan 401d8ee4a1cSLaxman Dewangan if (!bdata->timer_debounce) { 402d8ee4a1cSLaxman Dewangan input_event(input, EV_KEY, button->code, 0); 403d8ee4a1cSLaxman Dewangan input_sync(input); 404d8ee4a1cSLaxman Dewangan goto out; 405d8ee4a1cSLaxman Dewangan } 406d8ee4a1cSLaxman Dewangan 407d8ee4a1cSLaxman Dewangan bdata->key_pressed = true; 408d8ee4a1cSLaxman Dewangan } 409d8ee4a1cSLaxman Dewangan 410d8ee4a1cSLaxman Dewangan if (bdata->timer_debounce) 411d8ee4a1cSLaxman Dewangan mod_timer(&bdata->timer, 412d8ee4a1cSLaxman Dewangan jiffies + msecs_to_jiffies(bdata->timer_debounce)); 413d8ee4a1cSLaxman Dewangan out: 414d8ee4a1cSLaxman Dewangan spin_unlock_irqrestore(&bdata->lock, flags); 415d8ee4a1cSLaxman Dewangan return IRQ_HANDLED; 416d8ee4a1cSLaxman Dewangan } 417d8ee4a1cSLaxman Dewangan 4189e3af04fSMika Westerberg static int __devinit gpio_keys_setup_key(struct platform_device *pdev, 419d9080921SDmitry Torokhov struct input_dev *input, 420bc8f1eafSBen Dooks struct gpio_button_data *bdata, 421d9080921SDmitry Torokhov const struct gpio_keys_button *button) 422bc8f1eafSBen Dooks { 42392a47674SAlexander Stein const char *desc = button->desc ? button->desc : "gpio_keys"; 4249e3af04fSMika Westerberg struct device *dev = &pdev->dev; 425d8ee4a1cSLaxman Dewangan irq_handler_t isr; 4269e3af04fSMika Westerberg unsigned long irqflags; 427bc8f1eafSBen Dooks int irq, error; 428bc8f1eafSBen Dooks 429d9080921SDmitry Torokhov bdata->input = input; 430d9080921SDmitry Torokhov bdata->button = button; 431d8ee4a1cSLaxman Dewangan spin_lock_init(&bdata->lock); 432d8ee4a1cSLaxman Dewangan 433d8ee4a1cSLaxman Dewangan if (gpio_is_valid(button->gpio)) { 434bc8f1eafSBen Dooks 435bc8f1eafSBen Dooks error = gpio_request(button->gpio, desc); 436bc8f1eafSBen Dooks if (error < 0) { 437d8ee4a1cSLaxman Dewangan dev_err(dev, "Failed to request GPIO %d, error %d\n", 438bc8f1eafSBen Dooks button->gpio, error); 439d8ee4a1cSLaxman Dewangan return error; 440bc8f1eafSBen Dooks } 441bc8f1eafSBen Dooks 442bc8f1eafSBen Dooks error = gpio_direction_input(button->gpio); 443bc8f1eafSBen Dooks if (error < 0) { 444d8ee4a1cSLaxman Dewangan dev_err(dev, 445d8ee4a1cSLaxman Dewangan "Failed to configure direction for GPIO %d, error %d\n", 446bc8f1eafSBen Dooks button->gpio, error); 447d8ee4a1cSLaxman Dewangan goto fail; 448bc8f1eafSBen Dooks } 449bc8f1eafSBen Dooks 45028ed684fSGrazvydas Ignotas if (button->debounce_interval) { 45128ed684fSGrazvydas Ignotas error = gpio_set_debounce(button->gpio, 45228ed684fSGrazvydas Ignotas button->debounce_interval * 1000); 45328ed684fSGrazvydas Ignotas /* use timer if gpiolib doesn't provide debounce */ 45428ed684fSGrazvydas Ignotas if (error < 0) 455d8ee4a1cSLaxman Dewangan bdata->timer_debounce = 456d8ee4a1cSLaxman Dewangan button->debounce_interval; 45728ed684fSGrazvydas Ignotas } 45828ed684fSGrazvydas Ignotas 459bc8f1eafSBen Dooks irq = gpio_to_irq(button->gpio); 460bc8f1eafSBen Dooks if (irq < 0) { 461bc8f1eafSBen Dooks error = irq; 462d8ee4a1cSLaxman Dewangan dev_err(dev, 463d8ee4a1cSLaxman Dewangan "Unable to get irq number for GPIO %d, error %d\n", 464bc8f1eafSBen Dooks button->gpio, error); 465d8ee4a1cSLaxman Dewangan goto fail; 466d8ee4a1cSLaxman Dewangan } 467d8ee4a1cSLaxman Dewangan bdata->irq = irq; 468d8ee4a1cSLaxman Dewangan 469d8ee4a1cSLaxman Dewangan INIT_WORK(&bdata->work, gpio_keys_gpio_work_func); 470d8ee4a1cSLaxman Dewangan setup_timer(&bdata->timer, 471d8ee4a1cSLaxman Dewangan gpio_keys_gpio_timer, (unsigned long)bdata); 472d8ee4a1cSLaxman Dewangan 473d8ee4a1cSLaxman Dewangan isr = gpio_keys_gpio_isr; 474d8ee4a1cSLaxman Dewangan irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; 475d8ee4a1cSLaxman Dewangan 476d8ee4a1cSLaxman Dewangan } else { 477d8ee4a1cSLaxman Dewangan if (!button->irq) { 478d8ee4a1cSLaxman Dewangan dev_err(dev, "No IRQ specified\n"); 479d8ee4a1cSLaxman Dewangan return -EINVAL; 480d8ee4a1cSLaxman Dewangan } 481d8ee4a1cSLaxman Dewangan bdata->irq = button->irq; 482d8ee4a1cSLaxman Dewangan 483d8ee4a1cSLaxman Dewangan if (button->type && button->type != EV_KEY) { 484d8ee4a1cSLaxman Dewangan dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); 485d8ee4a1cSLaxman Dewangan return -EINVAL; 486bc8f1eafSBen Dooks } 487bc8f1eafSBen Dooks 488d8ee4a1cSLaxman Dewangan bdata->timer_debounce = button->debounce_interval; 489d8ee4a1cSLaxman Dewangan setup_timer(&bdata->timer, 490d8ee4a1cSLaxman Dewangan gpio_keys_irq_timer, (unsigned long)bdata); 491d8ee4a1cSLaxman Dewangan 492d8ee4a1cSLaxman Dewangan isr = gpio_keys_irq_isr; 493d8ee4a1cSLaxman Dewangan irqflags = 0; 494d8ee4a1cSLaxman Dewangan } 495d8ee4a1cSLaxman Dewangan 496d8ee4a1cSLaxman Dewangan input_set_capability(input, button->type ?: EV_KEY, button->code); 497d8ee4a1cSLaxman Dewangan 4989e3af04fSMika Westerberg /* 4999e3af04fSMika Westerberg * If platform has specified that the button can be disabled, 5009e3af04fSMika Westerberg * we don't want it to share the interrupt line. 5019e3af04fSMika Westerberg */ 5029e3af04fSMika Westerberg if (!button->can_disable) 5039e3af04fSMika Westerberg irqflags |= IRQF_SHARED; 5049e3af04fSMika Westerberg 505d8ee4a1cSLaxman Dewangan error = request_any_context_irq(bdata->irq, isr, irqflags, desc, bdata); 50694a8cab8SPhilippe Langlais if (error < 0) { 507bc8f1eafSBen Dooks dev_err(dev, "Unable to claim irq %d; error %d\n", 508d8ee4a1cSLaxman Dewangan bdata->irq, error); 509d8ee4a1cSLaxman Dewangan goto fail; 510bc8f1eafSBen Dooks } 511bc8f1eafSBen Dooks 512bc8f1eafSBen Dooks return 0; 513bc8f1eafSBen Dooks 514d8ee4a1cSLaxman Dewangan fail: 515d8ee4a1cSLaxman Dewangan if (gpio_is_valid(button->gpio)) 516bc8f1eafSBen Dooks gpio_free(button->gpio); 517d8ee4a1cSLaxman Dewangan 518bc8f1eafSBen Dooks return error; 519bc8f1eafSBen Dooks } 520bc8f1eafSBen Dooks 521173bdd74SShubhrajyoti D static int gpio_keys_open(struct input_dev *input) 522173bdd74SShubhrajyoti D { 523173bdd74SShubhrajyoti D struct gpio_keys_drvdata *ddata = input_get_drvdata(input); 524*219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = ddata->pdata; 525173bdd74SShubhrajyoti D 526*219edc71SAlexandre Pereira da Silva return pdata->enable ? pdata->enable(input->dev.parent) : 0; 527173bdd74SShubhrajyoti D } 528173bdd74SShubhrajyoti D 529173bdd74SShubhrajyoti D static void gpio_keys_close(struct input_dev *input) 530173bdd74SShubhrajyoti D { 531173bdd74SShubhrajyoti D struct gpio_keys_drvdata *ddata = input_get_drvdata(input); 532*219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = ddata->pdata; 533173bdd74SShubhrajyoti D 534*219edc71SAlexandre Pereira da Silva if (pdata->disable) 535*219edc71SAlexandre Pereira da Silva pdata->disable(input->dev.parent); 536173bdd74SShubhrajyoti D } 537173bdd74SShubhrajyoti D 538fd05d089SDavid Jander /* 539fd05d089SDavid Jander * Handlers for alternative sources of platform_data 540fd05d089SDavid Jander */ 541*219edc71SAlexandre Pereira da Silva 542fd05d089SDavid Jander #ifdef CONFIG_OF 543fd05d089SDavid Jander /* 544fd05d089SDavid Jander * Translate OpenFirmware node properties into platform_data 545fd05d089SDavid Jander */ 546*219edc71SAlexandre Pereira da Silva static struct gpio_keys_platform_data * __devinit 547*219edc71SAlexandre Pereira da Silva gpio_keys_get_devtree_pdata(struct device *dev) 548fd05d089SDavid Jander { 549fd05d089SDavid Jander struct device_node *node, *pp; 550*219edc71SAlexandre Pereira da Silva struct gpio_keys_platform_data *pdata; 551*219edc71SAlexandre Pereira da Silva struct gpio_keys_button *button; 552*219edc71SAlexandre Pereira da Silva int error; 553*219edc71SAlexandre Pereira da Silva int nbuttons; 554fd05d089SDavid Jander int i; 555fd05d089SDavid Jander 556fd05d089SDavid Jander node = dev->of_node; 557*219edc71SAlexandre Pereira da Silva if (!node) { 558*219edc71SAlexandre Pereira da Silva error = -ENODEV; 559*219edc71SAlexandre Pereira da Silva goto err_out; 560*219edc71SAlexandre Pereira da Silva } 561fd05d089SDavid Jander 562*219edc71SAlexandre Pereira da Silva nbuttons = of_get_child_count(node); 563*219edc71SAlexandre Pereira da Silva if (nbuttons == 0) { 564*219edc71SAlexandre Pereira da Silva error = -ENODEV; 565*219edc71SAlexandre Pereira da Silva goto err_out; 566*219edc71SAlexandre Pereira da Silva } 567*219edc71SAlexandre Pereira da Silva 568*219edc71SAlexandre Pereira da Silva pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), 569*219edc71SAlexandre Pereira da Silva GFP_KERNEL); 570*219edc71SAlexandre Pereira da Silva if (!pdata) { 571*219edc71SAlexandre Pereira da Silva error = -ENOMEM; 572*219edc71SAlexandre Pereira da Silva goto err_out; 573*219edc71SAlexandre Pereira da Silva } 574*219edc71SAlexandre Pereira da Silva 575*219edc71SAlexandre Pereira da Silva pdata->buttons = (struct gpio_keys_button *)(pdata + 1); 576*219edc71SAlexandre Pereira da Silva pdata->nbuttons = nbuttons; 577fd05d089SDavid Jander 578cca84699STobias Klauser pdata->rep = !!of_get_property(node, "autorepeat", NULL); 579fd05d089SDavid Jander 580fd05d089SDavid Jander i = 0; 581*219edc71SAlexandre Pereira da Silva for_each_child_of_node(node, pp) { 582fd05d089SDavid Jander enum of_gpio_flags flags; 583fd05d089SDavid Jander 584fd05d089SDavid Jander if (!of_find_property(pp, "gpios", NULL)) { 585fd05d089SDavid Jander pdata->nbuttons--; 586fd05d089SDavid Jander dev_warn(dev, "Found button without gpios\n"); 587fd05d089SDavid Jander continue; 588fd05d089SDavid Jander } 589fd05d089SDavid Jander 590*219edc71SAlexandre Pereira da Silva button = &pdata->buttons[i++]; 591fd05d089SDavid Jander 592*219edc71SAlexandre Pereira da Silva button->gpio = of_get_gpio_flags(pp, 0, &flags); 593*219edc71SAlexandre Pereira da Silva button->active_low = flags & OF_GPIO_ACTIVE_LOW; 594fd05d089SDavid Jander 595*219edc71SAlexandre Pereira da Silva if (of_property_read_u32(pp, "linux,code", &button->code)) { 596*219edc71SAlexandre Pereira da Silva dev_err(dev, "Button without keycode: 0x%x\n", 597*219edc71SAlexandre Pereira da Silva button->gpio); 598*219edc71SAlexandre Pereira da Silva error = -EINVAL; 599*219edc71SAlexandre Pereira da Silva goto err_free_pdata; 600fd05d089SDavid Jander } 601fd05d089SDavid Jander 602*219edc71SAlexandre Pereira da Silva button->desc = of_get_property(pp, "label", NULL); 603fd05d089SDavid Jander 604*219edc71SAlexandre Pereira da Silva if (of_property_read_u32(pp, "linux,input-type", &button->type)) 605*219edc71SAlexandre Pereira da Silva button->type = EV_KEY; 606fd05d089SDavid Jander 607*219edc71SAlexandre Pereira da Silva button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); 608*219edc71SAlexandre Pereira da Silva 609*219edc71SAlexandre Pereira da Silva if (of_property_read_u32(pp, "debounce-interval", 610*219edc71SAlexandre Pereira da Silva &button->debounce_interval)) 611*219edc71SAlexandre Pereira da Silva button->debounce_interval = 5; 612*219edc71SAlexandre Pereira da Silva } 613*219edc71SAlexandre Pereira da Silva 614*219edc71SAlexandre Pereira da Silva if (pdata->nbuttons == 0) { 615*219edc71SAlexandre Pereira da Silva error = -EINVAL; 616*219edc71SAlexandre Pereira da Silva goto err_free_pdata; 617*219edc71SAlexandre Pereira da Silva } 618*219edc71SAlexandre Pereira da Silva 619*219edc71SAlexandre Pereira da Silva return pdata; 620*219edc71SAlexandre Pereira da Silva 621*219edc71SAlexandre Pereira da Silva err_free_pdata: 622*219edc71SAlexandre Pereira da Silva kfree(pdata); 623*219edc71SAlexandre Pereira da Silva err_out: 624*219edc71SAlexandre Pereira da Silva return ERR_PTR(error); 625fd05d089SDavid Jander } 626fd05d089SDavid Jander 627fd05d089SDavid Jander static struct of_device_id gpio_keys_of_match[] = { 628fd05d089SDavid Jander { .compatible = "gpio-keys", }, 629fd05d089SDavid Jander { }, 630fd05d089SDavid Jander }; 631fd05d089SDavid Jander MODULE_DEVICE_TABLE(of, gpio_keys_of_match); 632fd05d089SDavid Jander 633fd05d089SDavid Jander #else 634fd05d089SDavid Jander 635*219edc71SAlexandre Pereira da Silva static inline struct gpio_keys_platform_data * 636*219edc71SAlexandre Pereira da Silva gpio_keys_get_devtree_pdata(struct device *dev) 637fd05d089SDavid Jander { 638*219edc71SAlexandre Pereira da Silva return ERR_PTR(-ENODEV); 639fd05d089SDavid Jander } 640fd05d089SDavid Jander 641fd05d089SDavid Jander #endif 642fd05d089SDavid Jander 643a16ca239SDmitry Torokhov static void gpio_remove_key(struct gpio_button_data *bdata) 644a16ca239SDmitry Torokhov { 645d8ee4a1cSLaxman Dewangan free_irq(bdata->irq, bdata); 646a16ca239SDmitry Torokhov if (bdata->timer_debounce) 647a16ca239SDmitry Torokhov del_timer_sync(&bdata->timer); 648a16ca239SDmitry Torokhov cancel_work_sync(&bdata->work); 649d8ee4a1cSLaxman Dewangan if (gpio_is_valid(bdata->button->gpio)) 650a16ca239SDmitry Torokhov gpio_free(bdata->button->gpio); 651a16ca239SDmitry Torokhov } 652a16ca239SDmitry Torokhov 65378a56aabSPhil Blundell static int __devinit gpio_keys_probe(struct platform_device *pdev) 65478a56aabSPhil Blundell { 655db19fd8bSBen Dooks struct device *dev = &pdev->dev; 656*219edc71SAlexandre Pereira da Silva const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); 657*219edc71SAlexandre Pereira da Silva struct gpio_keys_drvdata *ddata; 65878a56aabSPhil Blundell struct input_dev *input; 65978a56aabSPhil Blundell int i, error; 660e15b0213SAnti Sullin int wakeup = 0; 66178a56aabSPhil Blundell 662fd05d089SDavid Jander if (!pdata) { 663*219edc71SAlexandre Pereira da Silva pdata = gpio_keys_get_devtree_pdata(dev); 664*219edc71SAlexandre Pereira da Silva if (IS_ERR(pdata)) 665*219edc71SAlexandre Pereira da Silva return PTR_ERR(pdata); 666fd05d089SDavid Jander } 667fd05d089SDavid Jander 668a33466e3SDmitry Baryshkov ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + 669a33466e3SDmitry Baryshkov pdata->nbuttons * sizeof(struct gpio_button_data), 670a33466e3SDmitry Baryshkov GFP_KERNEL); 67178a56aabSPhil Blundell input = input_allocate_device(); 672a33466e3SDmitry Baryshkov if (!ddata || !input) { 673db19fd8bSBen Dooks dev_err(dev, "failed to allocate state\n"); 674a33466e3SDmitry Baryshkov error = -ENOMEM; 675a33466e3SDmitry Baryshkov goto fail1; 676a33466e3SDmitry Baryshkov } 67778a56aabSPhil Blundell 678*219edc71SAlexandre Pereira da Silva ddata->pdata = pdata; 6799e3af04fSMika Westerberg ddata->input = input; 6809e3af04fSMika Westerberg mutex_init(&ddata->disable_lock); 6819e3af04fSMika Westerberg 682a33466e3SDmitry Baryshkov platform_set_drvdata(pdev, ddata); 683173bdd74SShubhrajyoti D input_set_drvdata(input, ddata); 68478a56aabSPhil Blundell 68546711277SAlexander Stein input->name = pdata->name ? : pdev->name; 68678a56aabSPhil Blundell input->phys = "gpio-keys/input0"; 687469ba4dfSDmitry Torokhov input->dev.parent = &pdev->dev; 688173bdd74SShubhrajyoti D input->open = gpio_keys_open; 689173bdd74SShubhrajyoti D input->close = gpio_keys_close; 69078a56aabSPhil Blundell 69178a56aabSPhil Blundell input->id.bustype = BUS_HOST; 69278a56aabSPhil Blundell input->id.vendor = 0x0001; 69378a56aabSPhil Blundell input->id.product = 0x0001; 69478a56aabSPhil Blundell input->id.version = 0x0100; 69578a56aabSPhil Blundell 696b67b4b11SDominic Curran /* Enable auto repeat feature of Linux input subsystem */ 697b67b4b11SDominic Curran if (pdata->rep) 698b67b4b11SDominic Curran __set_bit(EV_REP, input->evbit); 699b67b4b11SDominic Curran 70078a56aabSPhil Blundell for (i = 0; i < pdata->nbuttons; i++) { 701d9080921SDmitry Torokhov const struct gpio_keys_button *button = &pdata->buttons[i]; 702a33466e3SDmitry Baryshkov struct gpio_button_data *bdata = &ddata->data[i]; 70378a56aabSPhil Blundell 704d9080921SDmitry Torokhov error = gpio_keys_setup_key(pdev, input, bdata, button); 705bc8f1eafSBen Dooks if (error) 706a33466e3SDmitry Baryshkov goto fail2; 70784767d00SRoman Moravcik 708e15b0213SAnti Sullin if (button->wakeup) 709e15b0213SAnti Sullin wakeup = 1; 71078a56aabSPhil Blundell } 71178a56aabSPhil Blundell 7129e3af04fSMika Westerberg error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); 7139e3af04fSMika Westerberg if (error) { 7149e3af04fSMika Westerberg dev_err(dev, "Unable to export keys/switches, error: %d\n", 7159e3af04fSMika Westerberg error); 7169e3af04fSMika Westerberg goto fail2; 7179e3af04fSMika Westerberg } 7189e3af04fSMika Westerberg 71978a56aabSPhil Blundell error = input_register_device(input); 72078a56aabSPhil Blundell if (error) { 7219e3af04fSMika Westerberg dev_err(dev, "Unable to register input device, error: %d\n", 7229e3af04fSMika Westerberg error); 7239e3af04fSMika Westerberg goto fail3; 72478a56aabSPhil Blundell } 72578a56aabSPhil Blundell 726d8ee4a1cSLaxman Dewangan /* get current state of buttons that are connected to GPIOs */ 727d8ee4a1cSLaxman Dewangan for (i = 0; i < pdata->nbuttons; i++) { 728d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = &ddata->data[i]; 729d8ee4a1cSLaxman Dewangan if (gpio_is_valid(bdata->button->gpio)) 730d8ee4a1cSLaxman Dewangan gpio_keys_gpio_report_event(bdata); 731d8ee4a1cSLaxman Dewangan } 7326ee88d71SDaniel Mack input_sync(input); 7336ee88d71SDaniel Mack 734e15b0213SAnti Sullin device_init_wakeup(&pdev->dev, wakeup); 735e15b0213SAnti Sullin 73678a56aabSPhil Blundell return 0; 73778a56aabSPhil Blundell 7389e3af04fSMika Westerberg fail3: 7399e3af04fSMika Westerberg sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); 740a33466e3SDmitry Baryshkov fail2: 741a16ca239SDmitry Torokhov while (--i >= 0) 742a16ca239SDmitry Torokhov gpio_remove_key(&ddata->data[i]); 74378a56aabSPhil Blundell 744006df302SAnti Sullin platform_set_drvdata(pdev, NULL); 745a33466e3SDmitry Baryshkov fail1: 74678a56aabSPhil Blundell input_free_device(input); 747a33466e3SDmitry Baryshkov kfree(ddata); 748*219edc71SAlexandre Pereira da Silva /* If we have no platform data, we allocated pdata dynamically. */ 749*219edc71SAlexandre Pereira da Silva if (!dev_get_platdata(&pdev->dev)) 750*219edc71SAlexandre Pereira da Silva kfree(pdata); 75178a56aabSPhil Blundell 75278a56aabSPhil Blundell return error; 75378a56aabSPhil Blundell } 75478a56aabSPhil Blundell 75578a56aabSPhil Blundell static int __devexit gpio_keys_remove(struct platform_device *pdev) 75678a56aabSPhil Blundell { 757a33466e3SDmitry Baryshkov struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); 758a33466e3SDmitry Baryshkov struct input_dev *input = ddata->input; 75978a56aabSPhil Blundell int i; 76078a56aabSPhil Blundell 7619e3af04fSMika Westerberg sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); 7629e3af04fSMika Westerberg 763e15b0213SAnti Sullin device_init_wakeup(&pdev->dev, 0); 764e15b0213SAnti Sullin 765*219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) 766a16ca239SDmitry Torokhov gpio_remove_key(&ddata->data[i]); 76778a56aabSPhil Blundell 76878a56aabSPhil Blundell input_unregister_device(input); 769fd05d089SDavid Jander 770*219edc71SAlexandre Pereira da Silva /* If we have no platform data, we allocated pdata dynamically. */ 771*219edc71SAlexandre Pereira da Silva if (!dev_get_platdata(&pdev->dev)) 772*219edc71SAlexandre Pereira da Silva kfree(ddata->pdata); 773fd05d089SDavid Jander 77416382079SAxel Lin kfree(ddata); 77578a56aabSPhil Blundell 77678a56aabSPhil Blundell return 0; 77778a56aabSPhil Blundell } 77878a56aabSPhil Blundell 779bdda8216SDmitry Torokhov #ifdef CONFIG_PM_SLEEP 780ae78e0e0SMike Rapoport static int gpio_keys_suspend(struct device *dev) 781e15b0213SAnti Sullin { 782fd05d089SDavid Jander struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 783e15b0213SAnti Sullin int i; 784e15b0213SAnti Sullin 785fd05d089SDavid Jander if (device_may_wakeup(dev)) { 786*219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 787d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = &ddata->data[i]; 788d8ee4a1cSLaxman Dewangan if (bdata->button->wakeup) 789d8ee4a1cSLaxman Dewangan enable_irq_wake(bdata->irq); 790e15b0213SAnti Sullin } 791e15b0213SAnti Sullin } 792e15b0213SAnti Sullin 793e15b0213SAnti Sullin return 0; 794e15b0213SAnti Sullin } 795e15b0213SAnti Sullin 796ae78e0e0SMike Rapoport static int gpio_keys_resume(struct device *dev) 797e15b0213SAnti Sullin { 798fd05d089SDavid Jander struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 799e15b0213SAnti Sullin int i; 800e15b0213SAnti Sullin 801*219edc71SAlexandre Pereira da Silva for (i = 0; i < ddata->pdata->nbuttons; i++) { 802d8ee4a1cSLaxman Dewangan struct gpio_button_data *bdata = &ddata->data[i]; 803d8ee4a1cSLaxman Dewangan if (bdata->button->wakeup && device_may_wakeup(dev)) 804d8ee4a1cSLaxman Dewangan disable_irq_wake(bdata->irq); 8056ee88d71SDaniel Mack 806d8ee4a1cSLaxman Dewangan if (gpio_is_valid(bdata->button->gpio)) 807d8ee4a1cSLaxman Dewangan gpio_keys_gpio_report_event(bdata); 808e15b0213SAnti Sullin } 8096ee88d71SDaniel Mack input_sync(ddata->input); 810e15b0213SAnti Sullin 811e15b0213SAnti Sullin return 0; 812e15b0213SAnti Sullin } 813e15b0213SAnti Sullin #endif 814e15b0213SAnti Sullin 815bdda8216SDmitry Torokhov static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); 816bdda8216SDmitry Torokhov 8179b07044cSUwe Kleine-König static struct platform_driver gpio_keys_device_driver = { 81878a56aabSPhil Blundell .probe = gpio_keys_probe, 81978a56aabSPhil Blundell .remove = __devexit_p(gpio_keys_remove), 82078a56aabSPhil Blundell .driver = { 82178a56aabSPhil Blundell .name = "gpio-keys", 822d7b5247bSKay Sievers .owner = THIS_MODULE, 823ae78e0e0SMike Rapoport .pm = &gpio_keys_pm_ops, 824*219edc71SAlexandre Pereira da Silva .of_match_table = of_match_ptr(gpio_keys_of_match), 82578a56aabSPhil Blundell } 82678a56aabSPhil Blundell }; 82778a56aabSPhil Blundell 82878a56aabSPhil Blundell static int __init gpio_keys_init(void) 82978a56aabSPhil Blundell { 83078a56aabSPhil Blundell return platform_driver_register(&gpio_keys_device_driver); 83178a56aabSPhil Blundell } 83278a56aabSPhil Blundell 83378a56aabSPhil Blundell static void __exit gpio_keys_exit(void) 83478a56aabSPhil Blundell { 83578a56aabSPhil Blundell platform_driver_unregister(&gpio_keys_device_driver); 83678a56aabSPhil Blundell } 83778a56aabSPhil Blundell 838b2330205SDavid Jander late_initcall(gpio_keys_init); 83978a56aabSPhil Blundell module_exit(gpio_keys_exit); 84078a56aabSPhil Blundell 84178a56aabSPhil Blundell MODULE_LICENSE("GPL"); 84278a56aabSPhil Blundell MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); 8437e2ecdf4SDavid Jander MODULE_DESCRIPTION("Keyboard driver for GPIOs"); 844d7b5247bSKay Sievers MODULE_ALIAS("platform:gpio-keys"); 845