178a56aabSPhil Blundell /* 278a56aabSPhil Blundell * Driver for keys on GPIO lines capable of generating interrupts. 378a56aabSPhil Blundell * 478a56aabSPhil Blundell * Copyright 2005 Phil Blundell 578a56aabSPhil Blundell * 678a56aabSPhil Blundell * This program is free software; you can redistribute it and/or modify 778a56aabSPhil Blundell * it under the terms of the GNU General Public License version 2 as 878a56aabSPhil Blundell * published by the Free Software Foundation. 978a56aabSPhil Blundell */ 1078a56aabSPhil Blundell 1178a56aabSPhil Blundell #include <linux/module.h> 1278a56aabSPhil Blundell 1378a56aabSPhil Blundell #include <linux/init.h> 1478a56aabSPhil Blundell #include <linux/fs.h> 1578a56aabSPhil Blundell #include <linux/interrupt.h> 1678a56aabSPhil Blundell #include <linux/irq.h> 1778a56aabSPhil Blundell #include <linux/sched.h> 1878a56aabSPhil Blundell #include <linux/pm.h> 19*5a0e3ad6STejun Heo #include <linux/slab.h> 2078a56aabSPhil Blundell #include <linux/sysctl.h> 2178a56aabSPhil Blundell #include <linux/proc_fs.h> 2278a56aabSPhil Blundell #include <linux/delay.h> 2378a56aabSPhil Blundell #include <linux/platform_device.h> 2478a56aabSPhil Blundell #include <linux/input.h> 2549015beeSDavid Brownell #include <linux/gpio_keys.h> 26da0d03feSJani Nikula #include <linux/workqueue.h> 27111bc59cSBen Dooks #include <linux/gpio.h> 2878a56aabSPhil Blundell 29a33466e3SDmitry Baryshkov struct gpio_button_data { 30a33466e3SDmitry Baryshkov struct gpio_keys_button *button; 31a33466e3SDmitry Baryshkov struct input_dev *input; 32ca865a77SJani Nikula struct timer_list timer; 33da0d03feSJani Nikula struct work_struct work; 349e3af04fSMika Westerberg bool disabled; 35a33466e3SDmitry Baryshkov }; 36a33466e3SDmitry Baryshkov 37a33466e3SDmitry Baryshkov struct gpio_keys_drvdata { 38a33466e3SDmitry Baryshkov struct input_dev *input; 399e3af04fSMika Westerberg struct mutex disable_lock; 409e3af04fSMika Westerberg unsigned int n_buttons; 41a33466e3SDmitry Baryshkov struct gpio_button_data data[0]; 42a33466e3SDmitry Baryshkov }; 43a33466e3SDmitry Baryshkov 449e3af04fSMika Westerberg /* 459e3af04fSMika Westerberg * SYSFS interface for enabling/disabling keys and switches: 469e3af04fSMika Westerberg * 479e3af04fSMika Westerberg * There are 4 attributes under /sys/devices/platform/gpio-keys/ 489e3af04fSMika Westerberg * keys [ro] - bitmap of keys (EV_KEY) which can be 499e3af04fSMika Westerberg * disabled 509e3af04fSMika Westerberg * switches [ro] - bitmap of switches (EV_SW) which can be 519e3af04fSMika Westerberg * disabled 529e3af04fSMika Westerberg * disabled_keys [rw] - bitmap of keys currently disabled 539e3af04fSMika Westerberg * disabled_switches [rw] - bitmap of switches currently disabled 549e3af04fSMika Westerberg * 559e3af04fSMika Westerberg * Userland can change these values and hence disable event generation 569e3af04fSMika Westerberg * for each key (or switch). Disabling a key means its interrupt line 579e3af04fSMika Westerberg * is disabled. 589e3af04fSMika Westerberg * 599e3af04fSMika Westerberg * For example, if we have following switches set up as gpio-keys: 609e3af04fSMika Westerberg * SW_DOCK = 5 619e3af04fSMika Westerberg * SW_CAMERA_LENS_COVER = 9 629e3af04fSMika Westerberg * SW_KEYPAD_SLIDE = 10 639e3af04fSMika Westerberg * SW_FRONT_PROXIMITY = 11 649e3af04fSMika Westerberg * This is read from switches: 659e3af04fSMika Westerberg * 11-9,5 669e3af04fSMika Westerberg * Next we want to disable proximity (11) and dock (5), we write: 679e3af04fSMika Westerberg * 11,5 689e3af04fSMika Westerberg * to file disabled_switches. Now proximity and dock IRQs are disabled. 699e3af04fSMika Westerberg * This can be verified by reading the file disabled_switches: 709e3af04fSMika Westerberg * 11,5 719e3af04fSMika Westerberg * If we now want to enable proximity (11) switch we write: 729e3af04fSMika Westerberg * 5 739e3af04fSMika Westerberg * to disabled_switches. 749e3af04fSMika Westerberg * 759e3af04fSMika Westerberg * We can disable only those keys which don't allow sharing the irq. 769e3af04fSMika Westerberg */ 779e3af04fSMika Westerberg 789e3af04fSMika Westerberg /** 799e3af04fSMika Westerberg * get_n_events_by_type() - returns maximum number of events per @type 809e3af04fSMika Westerberg * @type: type of button (%EV_KEY, %EV_SW) 819e3af04fSMika Westerberg * 829e3af04fSMika Westerberg * Return value of this function can be used to allocate bitmap 839e3af04fSMika Westerberg * large enough to hold all bits for given type. 849e3af04fSMika Westerberg */ 859e3af04fSMika Westerberg static inline int get_n_events_by_type(int type) 869e3af04fSMika Westerberg { 879e3af04fSMika Westerberg BUG_ON(type != EV_SW && type != EV_KEY); 889e3af04fSMika Westerberg 899e3af04fSMika Westerberg return (type == EV_KEY) ? KEY_CNT : SW_CNT; 909e3af04fSMika Westerberg } 919e3af04fSMika Westerberg 929e3af04fSMika Westerberg /** 939e3af04fSMika Westerberg * gpio_keys_disable_button() - disables given GPIO button 949e3af04fSMika Westerberg * @bdata: button data for button to be disabled 959e3af04fSMika Westerberg * 969e3af04fSMika Westerberg * Disables button pointed by @bdata. This is done by masking 979e3af04fSMika Westerberg * IRQ line. After this function is called, button won't generate 989e3af04fSMika Westerberg * input events anymore. Note that one can only disable buttons 999e3af04fSMika Westerberg * that don't share IRQs. 1009e3af04fSMika Westerberg * 1019e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1029e3af04fSMika Westerberg * this function to avoid races when concurrent threads are 1039e3af04fSMika Westerberg * disabling buttons at the same time. 1049e3af04fSMika Westerberg */ 1059e3af04fSMika Westerberg static void gpio_keys_disable_button(struct gpio_button_data *bdata) 1069e3af04fSMika Westerberg { 1079e3af04fSMika Westerberg if (!bdata->disabled) { 1089e3af04fSMika Westerberg /* 1099e3af04fSMika Westerberg * Disable IRQ and possible debouncing timer. 1109e3af04fSMika Westerberg */ 1119e3af04fSMika Westerberg disable_irq(gpio_to_irq(bdata->button->gpio)); 1129e3af04fSMika Westerberg if (bdata->button->debounce_interval) 1139e3af04fSMika Westerberg del_timer_sync(&bdata->timer); 1149e3af04fSMika Westerberg 1159e3af04fSMika Westerberg bdata->disabled = true; 1169e3af04fSMika Westerberg } 1179e3af04fSMika Westerberg } 1189e3af04fSMika Westerberg 1199e3af04fSMika Westerberg /** 1209e3af04fSMika Westerberg * gpio_keys_enable_button() - enables given GPIO button 1219e3af04fSMika Westerberg * @bdata: button data for button to be disabled 1229e3af04fSMika Westerberg * 1239e3af04fSMika Westerberg * Enables given button pointed by @bdata. 1249e3af04fSMika Westerberg * 1259e3af04fSMika Westerberg * Make sure that @bdata->disable_lock is locked when entering 1269e3af04fSMika Westerberg * this function to avoid races with concurrent threads trying 1279e3af04fSMika Westerberg * to enable the same button at the same time. 1289e3af04fSMika Westerberg */ 1299e3af04fSMika Westerberg static void gpio_keys_enable_button(struct gpio_button_data *bdata) 1309e3af04fSMika Westerberg { 1319e3af04fSMika Westerberg if (bdata->disabled) { 1329e3af04fSMika Westerberg enable_irq(gpio_to_irq(bdata->button->gpio)); 1339e3af04fSMika Westerberg bdata->disabled = false; 1349e3af04fSMika Westerberg } 1359e3af04fSMika Westerberg } 1369e3af04fSMika Westerberg 1379e3af04fSMika Westerberg /** 1389e3af04fSMika Westerberg * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons 1399e3af04fSMika Westerberg * @ddata: pointer to drvdata 1409e3af04fSMika Westerberg * @buf: buffer where stringified bitmap is written 1419e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 1429e3af04fSMika Westerberg * @only_disabled: does caller want only those buttons that are 1439e3af04fSMika Westerberg * currently disabled or all buttons that can be 1449e3af04fSMika Westerberg * disabled 1459e3af04fSMika Westerberg * 1469e3af04fSMika Westerberg * This function writes buttons that can be disabled to @buf. If 1479e3af04fSMika Westerberg * @only_disabled is true, then @buf contains only those buttons 1489e3af04fSMika Westerberg * that are currently disabled. Returns 0 on success or negative 1499e3af04fSMika Westerberg * errno on failure. 1509e3af04fSMika Westerberg */ 1519e3af04fSMika Westerberg static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, 1529e3af04fSMika Westerberg char *buf, unsigned int type, 1539e3af04fSMika Westerberg bool only_disabled) 1549e3af04fSMika Westerberg { 1559e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 1569e3af04fSMika Westerberg unsigned long *bits; 1579e3af04fSMika Westerberg ssize_t ret; 1589e3af04fSMika Westerberg int i; 1599e3af04fSMika Westerberg 1609e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 1619e3af04fSMika Westerberg if (!bits) 1629e3af04fSMika Westerberg return -ENOMEM; 1639e3af04fSMika Westerberg 1649e3af04fSMika Westerberg for (i = 0; i < ddata->n_buttons; i++) { 1659e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 1669e3af04fSMika Westerberg 1679e3af04fSMika Westerberg if (bdata->button->type != type) 1689e3af04fSMika Westerberg continue; 1699e3af04fSMika Westerberg 1709e3af04fSMika Westerberg if (only_disabled && !bdata->disabled) 1719e3af04fSMika Westerberg continue; 1729e3af04fSMika Westerberg 1739e3af04fSMika Westerberg __set_bit(bdata->button->code, bits); 1749e3af04fSMika Westerberg } 1759e3af04fSMika Westerberg 1769e3af04fSMika Westerberg ret = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, bits, n_events); 1779e3af04fSMika Westerberg buf[ret++] = '\n'; 1789e3af04fSMika Westerberg buf[ret] = '\0'; 1799e3af04fSMika Westerberg 1809e3af04fSMika Westerberg kfree(bits); 1819e3af04fSMika Westerberg 1829e3af04fSMika Westerberg return ret; 1839e3af04fSMika Westerberg } 1849e3af04fSMika Westerberg 1859e3af04fSMika Westerberg /** 1869e3af04fSMika Westerberg * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap 1879e3af04fSMika Westerberg * @ddata: pointer to drvdata 1889e3af04fSMika Westerberg * @buf: buffer from userspace that contains stringified bitmap 1899e3af04fSMika Westerberg * @type: button type (%EV_KEY, %EV_SW) 1909e3af04fSMika Westerberg * 1919e3af04fSMika Westerberg * This function parses stringified bitmap from @buf and disables/enables 1929e3af04fSMika Westerberg * GPIO buttons accordinly. Returns 0 on success and negative error 1939e3af04fSMika Westerberg * on failure. 1949e3af04fSMika Westerberg */ 1959e3af04fSMika Westerberg static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, 1969e3af04fSMika Westerberg const char *buf, unsigned int type) 1979e3af04fSMika Westerberg { 1989e3af04fSMika Westerberg int n_events = get_n_events_by_type(type); 1999e3af04fSMika Westerberg unsigned long *bits; 2009e3af04fSMika Westerberg ssize_t error; 2019e3af04fSMika Westerberg int i; 2029e3af04fSMika Westerberg 2039e3af04fSMika Westerberg bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); 2049e3af04fSMika Westerberg if (!bits) 2059e3af04fSMika Westerberg return -ENOMEM; 2069e3af04fSMika Westerberg 2079e3af04fSMika Westerberg error = bitmap_parselist(buf, bits, n_events); 2089e3af04fSMika Westerberg if (error) 2099e3af04fSMika Westerberg goto out; 2109e3af04fSMika Westerberg 2119e3af04fSMika Westerberg /* First validate */ 2129e3af04fSMika Westerberg for (i = 0; i < ddata->n_buttons; i++) { 2139e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2149e3af04fSMika Westerberg 2159e3af04fSMika Westerberg if (bdata->button->type != type) 2169e3af04fSMika Westerberg continue; 2179e3af04fSMika Westerberg 2189e3af04fSMika Westerberg if (test_bit(bdata->button->code, bits) && 2199e3af04fSMika Westerberg !bdata->button->can_disable) { 2209e3af04fSMika Westerberg error = -EINVAL; 2219e3af04fSMika Westerberg goto out; 2229e3af04fSMika Westerberg } 2239e3af04fSMika Westerberg } 2249e3af04fSMika Westerberg 2259e3af04fSMika Westerberg mutex_lock(&ddata->disable_lock); 2269e3af04fSMika Westerberg 2279e3af04fSMika Westerberg for (i = 0; i < ddata->n_buttons; i++) { 2289e3af04fSMika Westerberg struct gpio_button_data *bdata = &ddata->data[i]; 2299e3af04fSMika Westerberg 2309e3af04fSMika Westerberg if (bdata->button->type != type) 2319e3af04fSMika Westerberg continue; 2329e3af04fSMika Westerberg 2339e3af04fSMika Westerberg if (test_bit(bdata->button->code, bits)) 2349e3af04fSMika Westerberg gpio_keys_disable_button(bdata); 2359e3af04fSMika Westerberg else 2369e3af04fSMika Westerberg gpio_keys_enable_button(bdata); 2379e3af04fSMika Westerberg } 2389e3af04fSMika Westerberg 2399e3af04fSMika Westerberg mutex_unlock(&ddata->disable_lock); 2409e3af04fSMika Westerberg 2419e3af04fSMika Westerberg out: 2429e3af04fSMika Westerberg kfree(bits); 2439e3af04fSMika Westerberg return error; 2449e3af04fSMika Westerberg } 2459e3af04fSMika Westerberg 2469e3af04fSMika Westerberg #define ATTR_SHOW_FN(name, type, only_disabled) \ 2479e3af04fSMika Westerberg static ssize_t gpio_keys_show_##name(struct device *dev, \ 2489e3af04fSMika Westerberg struct device_attribute *attr, \ 2499e3af04fSMika Westerberg char *buf) \ 2509e3af04fSMika Westerberg { \ 2519e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 2529e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 2539e3af04fSMika Westerberg \ 2549e3af04fSMika Westerberg return gpio_keys_attr_show_helper(ddata, buf, \ 2559e3af04fSMika Westerberg type, only_disabled); \ 2569e3af04fSMika Westerberg } 2579e3af04fSMika Westerberg 2589e3af04fSMika Westerberg ATTR_SHOW_FN(keys, EV_KEY, false); 2599e3af04fSMika Westerberg ATTR_SHOW_FN(switches, EV_SW, false); 2609e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_keys, EV_KEY, true); 2619e3af04fSMika Westerberg ATTR_SHOW_FN(disabled_switches, EV_SW, true); 2629e3af04fSMika Westerberg 2639e3af04fSMika Westerberg /* 2649e3af04fSMika Westerberg * ATTRIBUTES: 2659e3af04fSMika Westerberg * 2669e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/keys [ro] 2679e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/switches [ro] 2689e3af04fSMika Westerberg */ 2699e3af04fSMika Westerberg static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL); 2709e3af04fSMika Westerberg static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL); 2719e3af04fSMika Westerberg 2729e3af04fSMika Westerberg #define ATTR_STORE_FN(name, type) \ 2739e3af04fSMika Westerberg static ssize_t gpio_keys_store_##name(struct device *dev, \ 2749e3af04fSMika Westerberg struct device_attribute *attr, \ 2759e3af04fSMika Westerberg const char *buf, \ 2769e3af04fSMika Westerberg size_t count) \ 2779e3af04fSMika Westerberg { \ 2789e3af04fSMika Westerberg struct platform_device *pdev = to_platform_device(dev); \ 2799e3af04fSMika Westerberg struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ 2809e3af04fSMika Westerberg ssize_t error; \ 2819e3af04fSMika Westerberg \ 2829e3af04fSMika Westerberg error = gpio_keys_attr_store_helper(ddata, buf, type); \ 2839e3af04fSMika Westerberg if (error) \ 2849e3af04fSMika Westerberg return error; \ 2859e3af04fSMika Westerberg \ 2869e3af04fSMika Westerberg return count; \ 2879e3af04fSMika Westerberg } 2889e3af04fSMika Westerberg 2899e3af04fSMika Westerberg ATTR_STORE_FN(disabled_keys, EV_KEY); 2909e3af04fSMika Westerberg ATTR_STORE_FN(disabled_switches, EV_SW); 2919e3af04fSMika Westerberg 2929e3af04fSMika Westerberg /* 2939e3af04fSMika Westerberg * ATTRIBUTES: 2949e3af04fSMika Westerberg * 2959e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disabled_keys [rw] 2969e3af04fSMika Westerberg * /sys/devices/platform/gpio-keys/disables_switches [rw] 2979e3af04fSMika Westerberg */ 2989e3af04fSMika Westerberg static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO, 2999e3af04fSMika Westerberg gpio_keys_show_disabled_keys, 3009e3af04fSMika Westerberg gpio_keys_store_disabled_keys); 3019e3af04fSMika Westerberg static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO, 3029e3af04fSMika Westerberg gpio_keys_show_disabled_switches, 3039e3af04fSMika Westerberg gpio_keys_store_disabled_switches); 3049e3af04fSMika Westerberg 3059e3af04fSMika Westerberg static struct attribute *gpio_keys_attrs[] = { 3069e3af04fSMika Westerberg &dev_attr_keys.attr, 3079e3af04fSMika Westerberg &dev_attr_switches.attr, 3089e3af04fSMika Westerberg &dev_attr_disabled_keys.attr, 3099e3af04fSMika Westerberg &dev_attr_disabled_switches.attr, 3109e3af04fSMika Westerberg NULL, 3119e3af04fSMika Westerberg }; 3129e3af04fSMika Westerberg 3139e3af04fSMika Westerberg static struct attribute_group gpio_keys_attr_group = { 3149e3af04fSMika Westerberg .attrs = gpio_keys_attrs, 3159e3af04fSMika Westerberg }; 3169e3af04fSMika Westerberg 3176ee88d71SDaniel Mack static void gpio_keys_report_event(struct gpio_button_data *bdata) 31878a56aabSPhil Blundell { 319ce25d7e9SUwe Kleine-König struct gpio_keys_button *button = bdata->button; 320ce25d7e9SUwe Kleine-König struct input_dev *input = bdata->input; 32184767d00SRoman Moravcik unsigned int type = button->type ?: EV_KEY; 322a33466e3SDmitry Baryshkov int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; 32384767d00SRoman Moravcik 32484767d00SRoman Moravcik input_event(input, type, button->code, !!state); 32578a56aabSPhil Blundell input_sync(input); 326a33466e3SDmitry Baryshkov } 327a33466e3SDmitry Baryshkov 3286ee88d71SDaniel Mack static void gpio_keys_work_func(struct work_struct *work) 3296ee88d71SDaniel Mack { 3306ee88d71SDaniel Mack struct gpio_button_data *bdata = 3316ee88d71SDaniel Mack container_of(work, struct gpio_button_data, work); 3326ee88d71SDaniel Mack 3336ee88d71SDaniel Mack gpio_keys_report_event(bdata); 3346ee88d71SDaniel Mack } 3356ee88d71SDaniel Mack 336da0d03feSJani Nikula static void gpio_keys_timer(unsigned long _data) 337ca865a77SJani Nikula { 338ca865a77SJani Nikula struct gpio_button_data *data = (struct gpio_button_data *)_data; 339ca865a77SJani Nikula 340da0d03feSJani Nikula schedule_work(&data->work); 341ca865a77SJani Nikula } 342ca865a77SJani Nikula 343a33466e3SDmitry Baryshkov static irqreturn_t gpio_keys_isr(int irq, void *dev_id) 344a33466e3SDmitry Baryshkov { 34557ffe9d5SUwe Kleine-König struct gpio_button_data *bdata = dev_id; 34657ffe9d5SUwe Kleine-König struct gpio_keys_button *button = bdata->button; 347a33466e3SDmitry Baryshkov 34857ffe9d5SUwe Kleine-König BUG_ON(irq != gpio_to_irq(button->gpio)); 349a33466e3SDmitry Baryshkov 350ca865a77SJani Nikula if (button->debounce_interval) 351ca865a77SJani Nikula mod_timer(&bdata->timer, 352ca865a77SJani Nikula jiffies + msecs_to_jiffies(button->debounce_interval)); 353ca865a77SJani Nikula else 354da0d03feSJani Nikula schedule_work(&bdata->work); 355a33466e3SDmitry Baryshkov 3561164ec1aSDavid Brownell return IRQ_HANDLED; 35778a56aabSPhil Blundell } 35878a56aabSPhil Blundell 3599e3af04fSMika Westerberg static int __devinit gpio_keys_setup_key(struct platform_device *pdev, 360bc8f1eafSBen Dooks struct gpio_button_data *bdata, 361bc8f1eafSBen Dooks struct gpio_keys_button *button) 362bc8f1eafSBen Dooks { 363bc8f1eafSBen Dooks char *desc = button->desc ? button->desc : "gpio_keys"; 3649e3af04fSMika Westerberg struct device *dev = &pdev->dev; 3659e3af04fSMika Westerberg unsigned long irqflags; 366bc8f1eafSBen Dooks int irq, error; 367bc8f1eafSBen Dooks 368bc8f1eafSBen Dooks setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata); 3696ee88d71SDaniel Mack INIT_WORK(&bdata->work, gpio_keys_work_func); 370bc8f1eafSBen Dooks 371bc8f1eafSBen Dooks error = gpio_request(button->gpio, desc); 372bc8f1eafSBen Dooks if (error < 0) { 373bc8f1eafSBen Dooks dev_err(dev, "failed to request GPIO %d, error %d\n", 374bc8f1eafSBen Dooks button->gpio, error); 375bc8f1eafSBen Dooks goto fail2; 376bc8f1eafSBen Dooks } 377bc8f1eafSBen Dooks 378bc8f1eafSBen Dooks error = gpio_direction_input(button->gpio); 379bc8f1eafSBen Dooks if (error < 0) { 380bc8f1eafSBen Dooks dev_err(dev, "failed to configure" 381bc8f1eafSBen Dooks " direction for GPIO %d, error %d\n", 382bc8f1eafSBen Dooks button->gpio, error); 383bc8f1eafSBen Dooks goto fail3; 384bc8f1eafSBen Dooks } 385bc8f1eafSBen Dooks 386bc8f1eafSBen Dooks irq = gpio_to_irq(button->gpio); 387bc8f1eafSBen Dooks if (irq < 0) { 388bc8f1eafSBen Dooks error = irq; 389bc8f1eafSBen Dooks dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", 390bc8f1eafSBen Dooks button->gpio, error); 391bc8f1eafSBen Dooks goto fail3; 392bc8f1eafSBen Dooks } 393bc8f1eafSBen Dooks 3949e3af04fSMika Westerberg irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; 3959e3af04fSMika Westerberg /* 3969e3af04fSMika Westerberg * If platform has specified that the button can be disabled, 3979e3af04fSMika Westerberg * we don't want it to share the interrupt line. 3989e3af04fSMika Westerberg */ 3999e3af04fSMika Westerberg if (!button->can_disable) 4009e3af04fSMika Westerberg irqflags |= IRQF_SHARED; 4019e3af04fSMika Westerberg 4029e3af04fSMika Westerberg error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata); 403bc8f1eafSBen Dooks if (error) { 404bc8f1eafSBen Dooks dev_err(dev, "Unable to claim irq %d; error %d\n", 405bc8f1eafSBen Dooks irq, error); 406bc8f1eafSBen Dooks goto fail3; 407bc8f1eafSBen Dooks } 408bc8f1eafSBen Dooks 409bc8f1eafSBen Dooks return 0; 410bc8f1eafSBen Dooks 411bc8f1eafSBen Dooks fail3: 412bc8f1eafSBen Dooks gpio_free(button->gpio); 413bc8f1eafSBen Dooks fail2: 414bc8f1eafSBen Dooks return error; 415bc8f1eafSBen Dooks } 416bc8f1eafSBen Dooks 41778a56aabSPhil Blundell static int __devinit gpio_keys_probe(struct platform_device *pdev) 41878a56aabSPhil Blundell { 41978a56aabSPhil Blundell struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 420a33466e3SDmitry Baryshkov struct gpio_keys_drvdata *ddata; 421db19fd8bSBen Dooks struct device *dev = &pdev->dev; 42278a56aabSPhil Blundell struct input_dev *input; 42378a56aabSPhil Blundell int i, error; 424e15b0213SAnti Sullin int wakeup = 0; 42578a56aabSPhil Blundell 426a33466e3SDmitry Baryshkov ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + 427a33466e3SDmitry Baryshkov pdata->nbuttons * sizeof(struct gpio_button_data), 428a33466e3SDmitry Baryshkov GFP_KERNEL); 42978a56aabSPhil Blundell input = input_allocate_device(); 430a33466e3SDmitry Baryshkov if (!ddata || !input) { 431db19fd8bSBen Dooks dev_err(dev, "failed to allocate state\n"); 432a33466e3SDmitry Baryshkov error = -ENOMEM; 433a33466e3SDmitry Baryshkov goto fail1; 434a33466e3SDmitry Baryshkov } 43578a56aabSPhil Blundell 4369e3af04fSMika Westerberg ddata->input = input; 4379e3af04fSMika Westerberg ddata->n_buttons = pdata->nbuttons; 4389e3af04fSMika Westerberg mutex_init(&ddata->disable_lock); 4399e3af04fSMika Westerberg 440a33466e3SDmitry Baryshkov platform_set_drvdata(pdev, ddata); 44178a56aabSPhil Blundell 44278a56aabSPhil Blundell input->name = pdev->name; 44378a56aabSPhil Blundell input->phys = "gpio-keys/input0"; 444469ba4dfSDmitry Torokhov input->dev.parent = &pdev->dev; 44578a56aabSPhil Blundell 44678a56aabSPhil Blundell input->id.bustype = BUS_HOST; 44778a56aabSPhil Blundell input->id.vendor = 0x0001; 44878a56aabSPhil Blundell input->id.product = 0x0001; 44978a56aabSPhil Blundell input->id.version = 0x0100; 45078a56aabSPhil Blundell 451b67b4b11SDominic Curran /* Enable auto repeat feature of Linux input subsystem */ 452b67b4b11SDominic Curran if (pdata->rep) 453b67b4b11SDominic Curran __set_bit(EV_REP, input->evbit); 454b67b4b11SDominic Curran 45578a56aabSPhil Blundell for (i = 0; i < pdata->nbuttons; i++) { 45684767d00SRoman Moravcik struct gpio_keys_button *button = &pdata->buttons[i]; 457a33466e3SDmitry Baryshkov struct gpio_button_data *bdata = &ddata->data[i]; 45884767d00SRoman Moravcik unsigned int type = button->type ?: EV_KEY; 45978a56aabSPhil Blundell 460a33466e3SDmitry Baryshkov bdata->input = input; 46174dd4393SUwe Kleine-König bdata->button = button; 462a33466e3SDmitry Baryshkov 4639e3af04fSMika Westerberg error = gpio_keys_setup_key(pdev, bdata, button); 464bc8f1eafSBen Dooks if (error) 465a33466e3SDmitry Baryshkov goto fail2; 46684767d00SRoman Moravcik 467e15b0213SAnti Sullin if (button->wakeup) 468e15b0213SAnti Sullin wakeup = 1; 469e15b0213SAnti Sullin 47084767d00SRoman Moravcik input_set_capability(input, type, button->code); 47178a56aabSPhil Blundell } 47278a56aabSPhil Blundell 4739e3af04fSMika Westerberg error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); 4749e3af04fSMika Westerberg if (error) { 4759e3af04fSMika Westerberg dev_err(dev, "Unable to export keys/switches, error: %d\n", 4769e3af04fSMika Westerberg error); 4779e3af04fSMika Westerberg goto fail2; 4789e3af04fSMika Westerberg } 4799e3af04fSMika Westerberg 48078a56aabSPhil Blundell error = input_register_device(input); 48178a56aabSPhil Blundell if (error) { 4829e3af04fSMika Westerberg dev_err(dev, "Unable to register input device, error: %d\n", 4839e3af04fSMika Westerberg error); 4849e3af04fSMika Westerberg goto fail3; 48578a56aabSPhil Blundell } 48678a56aabSPhil Blundell 4876ee88d71SDaniel Mack /* get current state of buttons */ 4886ee88d71SDaniel Mack for (i = 0; i < pdata->nbuttons; i++) 4896ee88d71SDaniel Mack gpio_keys_report_event(&ddata->data[i]); 4906ee88d71SDaniel Mack input_sync(input); 4916ee88d71SDaniel Mack 492e15b0213SAnti Sullin device_init_wakeup(&pdev->dev, wakeup); 493e15b0213SAnti Sullin 49478a56aabSPhil Blundell return 0; 49578a56aabSPhil Blundell 4969e3af04fSMika Westerberg fail3: 4979e3af04fSMika Westerberg sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); 498a33466e3SDmitry Baryshkov fail2: 4996a2e3911SHerbert Valerio Riedel while (--i >= 0) { 50057ffe9d5SUwe Kleine-König free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); 501ca865a77SJani Nikula if (pdata->buttons[i].debounce_interval) 502ca865a77SJani Nikula del_timer_sync(&ddata->data[i].timer); 503da0d03feSJani Nikula cancel_work_sync(&ddata->data[i].work); 5046a2e3911SHerbert Valerio Riedel gpio_free(pdata->buttons[i].gpio); 5056a2e3911SHerbert Valerio Riedel } 50678a56aabSPhil Blundell 507006df302SAnti Sullin platform_set_drvdata(pdev, NULL); 508a33466e3SDmitry Baryshkov fail1: 50978a56aabSPhil Blundell input_free_device(input); 510a33466e3SDmitry Baryshkov kfree(ddata); 51178a56aabSPhil Blundell 51278a56aabSPhil Blundell return error; 51378a56aabSPhil Blundell } 51478a56aabSPhil Blundell 51578a56aabSPhil Blundell static int __devexit gpio_keys_remove(struct platform_device *pdev) 51678a56aabSPhil Blundell { 51778a56aabSPhil Blundell struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 518a33466e3SDmitry Baryshkov struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); 519a33466e3SDmitry Baryshkov struct input_dev *input = ddata->input; 52078a56aabSPhil Blundell int i; 52178a56aabSPhil Blundell 5229e3af04fSMika Westerberg sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); 5239e3af04fSMika Westerberg 524e15b0213SAnti Sullin device_init_wakeup(&pdev->dev, 0); 525e15b0213SAnti Sullin 52678a56aabSPhil Blundell for (i = 0; i < pdata->nbuttons; i++) { 5270d98f6bbSPhilipp Zabel int irq = gpio_to_irq(pdata->buttons[i].gpio); 52857ffe9d5SUwe Kleine-König free_irq(irq, &ddata->data[i]); 529ca865a77SJani Nikula if (pdata->buttons[i].debounce_interval) 530ca865a77SJani Nikula del_timer_sync(&ddata->data[i].timer); 531da0d03feSJani Nikula cancel_work_sync(&ddata->data[i].work); 5326a2e3911SHerbert Valerio Riedel gpio_free(pdata->buttons[i].gpio); 53378a56aabSPhil Blundell } 53478a56aabSPhil Blundell 53578a56aabSPhil Blundell input_unregister_device(input); 53678a56aabSPhil Blundell 53778a56aabSPhil Blundell return 0; 53878a56aabSPhil Blundell } 53978a56aabSPhil Blundell 540e15b0213SAnti Sullin 541e15b0213SAnti Sullin #ifdef CONFIG_PM 542ae78e0e0SMike Rapoport static int gpio_keys_suspend(struct device *dev) 543e15b0213SAnti Sullin { 544ae78e0e0SMike Rapoport struct platform_device *pdev = to_platform_device(dev); 545e15b0213SAnti Sullin struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 546e15b0213SAnti Sullin int i; 547e15b0213SAnti Sullin 548e15b0213SAnti Sullin if (device_may_wakeup(&pdev->dev)) { 549e15b0213SAnti Sullin for (i = 0; i < pdata->nbuttons; i++) { 550e15b0213SAnti Sullin struct gpio_keys_button *button = &pdata->buttons[i]; 551e15b0213SAnti Sullin if (button->wakeup) { 552e15b0213SAnti Sullin int irq = gpio_to_irq(button->gpio); 553e15b0213SAnti Sullin enable_irq_wake(irq); 554e15b0213SAnti Sullin } 555e15b0213SAnti Sullin } 556e15b0213SAnti Sullin } 557e15b0213SAnti Sullin 558e15b0213SAnti Sullin return 0; 559e15b0213SAnti Sullin } 560e15b0213SAnti Sullin 561ae78e0e0SMike Rapoport static int gpio_keys_resume(struct device *dev) 562e15b0213SAnti Sullin { 563ae78e0e0SMike Rapoport struct platform_device *pdev = to_platform_device(dev); 5646ee88d71SDaniel Mack struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); 565e15b0213SAnti Sullin struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 566e15b0213SAnti Sullin int i; 567e15b0213SAnti Sullin 568e15b0213SAnti Sullin for (i = 0; i < pdata->nbuttons; i++) { 5696ee88d71SDaniel Mack 570e15b0213SAnti Sullin struct gpio_keys_button *button = &pdata->buttons[i]; 5716ee88d71SDaniel Mack if (button->wakeup && device_may_wakeup(&pdev->dev)) { 572e15b0213SAnti Sullin int irq = gpio_to_irq(button->gpio); 573e15b0213SAnti Sullin disable_irq_wake(irq); 574e15b0213SAnti Sullin } 5756ee88d71SDaniel Mack 5766ee88d71SDaniel Mack gpio_keys_report_event(&ddata->data[i]); 577e15b0213SAnti Sullin } 5786ee88d71SDaniel Mack input_sync(ddata->input); 579e15b0213SAnti Sullin 580e15b0213SAnti Sullin return 0; 581e15b0213SAnti Sullin } 582ae78e0e0SMike Rapoport 583ae78e0e0SMike Rapoport static const struct dev_pm_ops gpio_keys_pm_ops = { 584ae78e0e0SMike Rapoport .suspend = gpio_keys_suspend, 585ae78e0e0SMike Rapoport .resume = gpio_keys_resume, 586ae78e0e0SMike Rapoport }; 587e15b0213SAnti Sullin #endif 588e15b0213SAnti Sullin 5899b07044cSUwe Kleine-König static struct platform_driver gpio_keys_device_driver = { 59078a56aabSPhil Blundell .probe = gpio_keys_probe, 59178a56aabSPhil Blundell .remove = __devexit_p(gpio_keys_remove), 59278a56aabSPhil Blundell .driver = { 59378a56aabSPhil Blundell .name = "gpio-keys", 594d7b5247bSKay Sievers .owner = THIS_MODULE, 595ae78e0e0SMike Rapoport #ifdef CONFIG_PM 596ae78e0e0SMike Rapoport .pm = &gpio_keys_pm_ops, 597ae78e0e0SMike Rapoport #endif 59878a56aabSPhil Blundell } 59978a56aabSPhil Blundell }; 60078a56aabSPhil Blundell 60178a56aabSPhil Blundell static int __init gpio_keys_init(void) 60278a56aabSPhil Blundell { 60378a56aabSPhil Blundell return platform_driver_register(&gpio_keys_device_driver); 60478a56aabSPhil Blundell } 60578a56aabSPhil Blundell 60678a56aabSPhil Blundell static void __exit gpio_keys_exit(void) 60778a56aabSPhil Blundell { 60878a56aabSPhil Blundell platform_driver_unregister(&gpio_keys_device_driver); 60978a56aabSPhil Blundell } 61078a56aabSPhil Blundell 61178a56aabSPhil Blundell module_init(gpio_keys_init); 61278a56aabSPhil Blundell module_exit(gpio_keys_exit); 61378a56aabSPhil Blundell 61478a56aabSPhil Blundell MODULE_LICENSE("GPL"); 61578a56aabSPhil Blundell MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); 61678a56aabSPhil Blundell MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); 617d7b5247bSKay Sievers MODULE_ALIAS("platform:gpio-keys"); 618