Loading Documentation/devicetree/bindings/gpio/gpio_keys.txt +3 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ Optional properties: config defined in pin groups of interrupt and reset gpio. "gpio_ts_suspend" : Disabled configuration of pins, this should specify sleep config defined in pin groups of interrupt and reset gpio. - name : input device name. - use-syscore : use syscore functionality for driver. Each button (key) is represented as a sub-node of "gpio-keys": Subnode properties: Loading @@ -42,6 +44,7 @@ Example nodes: pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend"; pinctrl-0 = <&gpio_key_active>; pinctrl-1 = <&gpio_key_suspend>; use-syscore; button@21 { label = "GPIO Key UP"; linux,code = <103>; Loading drivers/input/keyboard/gpio_keys.c +75 −2 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ * * Copyright 2005 Phil Blundell * Copyright 2010, 2011 David Jander <david@protonic.nl> * Copyright (c) 2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as Loading Loading @@ -31,6 +32,7 @@ #include <linux/of_gpio.h> #include <linux/spinlock.h> #include <linux/pinctrl/consumer.h> #include <linux/syscore_ops.h> struct gpio_button_data { const struct gpio_keys_button *button; Loading @@ -52,6 +54,11 @@ struct gpio_keys_drvdata { struct gpio_button_data data[0]; }; static struct device *global_dev; static struct syscore_ops gpio_keys_syscore_pm_ops; static void gpio_keys_syscore_resume(void); /* * SYSFS interface for enabling/disabling keys and switches: * Loading Loading @@ -330,7 +337,9 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) const struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; int state; state = (__gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; if (type == EV_ABS) { if (state) Loading Loading @@ -651,6 +660,8 @@ gpio_keys_get_devtree_pdata(struct device *dev) pdata->nbuttons = nbuttons; pdata->rep = !!of_get_property(node, "autorepeat", NULL); pdata->name = of_get_property(node, "input-name", NULL); pdata->use_syscore = of_property_read_bool(node, "use-syscore"); i = 0; for_each_child_of_node(node, pp) { Loading Loading @@ -749,6 +760,7 @@ static int gpio_keys_probe(struct platform_device *pdev) return -ENOMEM; } global_dev = dev; ddata->pdata = pdata; ddata->input = input; mutex_init(&ddata->disable_lock); Loading Loading @@ -817,6 +829,11 @@ static int gpio_keys_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, wakeup); if (pdata->use_syscore) gpio_keys_syscore_pm_ops.resume = gpio_keys_syscore_resume; register_syscore_ops(&gpio_keys_syscore_pm_ops); return 0; err_remove_group: Loading @@ -839,6 +856,7 @@ err_setup_key: static int gpio_keys_remove(struct platform_device *pdev) { sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); unregister_syscore_ops(&gpio_keys_syscore_pm_ops); device_init_wakeup(&pdev->dev, 0); Loading @@ -846,6 +864,41 @@ static int gpio_keys_remove(struct platform_device *pdev) } #ifdef CONFIG_PM_SLEEP static void gpio_keys_syscore_resume(void) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(global_dev); struct input_dev *input = ddata->input; struct gpio_button_data *bdata = NULL; int error = 0; int i; if (ddata->key_pinctrl) { error = gpio_keys_pinctrl_configure(ddata, true); if (error) { dev_err(global_dev, "failed to put the pin in resume state\n"); return; } } if (device_may_wakeup(global_dev)) { for (i = 0; i < ddata->pdata->nbuttons; i++) { bdata = &ddata->data[i]; if (bdata->button->wakeup) disable_irq_wake(bdata->irq); } } else { mutex_lock(&input->mutex); if (input->users) error = gpio_keys_open(input); mutex_unlock(&input->mutex); } if (error) return; gpio_keys_report_state(ddata); } static int gpio_keys_suspend(struct device *dev) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); Loading Loading @@ -883,6 +936,11 @@ static int gpio_keys_resume(struct device *dev) int error = 0; int i; if (ddata->pdata->use_syscore == true) { dev_dbg(global_dev, "Using syscore resume, no need of this resume.\n"); return 0; } if (ddata->key_pinctrl) { error = gpio_keys_pinctrl_configure(ddata, true); if (error) { Loading Loading @@ -910,6 +968,21 @@ static int gpio_keys_resume(struct device *dev) gpio_keys_report_state(ddata); return 0; } #else static void gpio_keys_syscore_resume(void){} static int gpio_keys_suspend(struct device *dev) { return 0; } static int gpio_keys_resume(struct device *dev) { return 0; } #endif static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); Loading include/linux/gpio_keys.h +2 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,8 @@ struct gpio_keys_platform_data { unsigned int rep:1; int (*enable)(struct device *dev); void (*disable)(struct device *dev); const char *name; const char *name; /* input device name */ bool use_syscore; }; #endif Loading
Documentation/devicetree/bindings/gpio/gpio_keys.txt +3 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ Optional properties: config defined in pin groups of interrupt and reset gpio. "gpio_ts_suspend" : Disabled configuration of pins, this should specify sleep config defined in pin groups of interrupt and reset gpio. - name : input device name. - use-syscore : use syscore functionality for driver. Each button (key) is represented as a sub-node of "gpio-keys": Subnode properties: Loading @@ -42,6 +44,7 @@ Example nodes: pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend"; pinctrl-0 = <&gpio_key_active>; pinctrl-1 = <&gpio_key_suspend>; use-syscore; button@21 { label = "GPIO Key UP"; linux,code = <103>; Loading
drivers/input/keyboard/gpio_keys.c +75 −2 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ * * Copyright 2005 Phil Blundell * Copyright 2010, 2011 David Jander <david@protonic.nl> * Copyright (c) 2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as Loading Loading @@ -31,6 +32,7 @@ #include <linux/of_gpio.h> #include <linux/spinlock.h> #include <linux/pinctrl/consumer.h> #include <linux/syscore_ops.h> struct gpio_button_data { const struct gpio_keys_button *button; Loading @@ -52,6 +54,11 @@ struct gpio_keys_drvdata { struct gpio_button_data data[0]; }; static struct device *global_dev; static struct syscore_ops gpio_keys_syscore_pm_ops; static void gpio_keys_syscore_resume(void); /* * SYSFS interface for enabling/disabling keys and switches: * Loading Loading @@ -330,7 +337,9 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) const struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; int state; state = (__gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; if (type == EV_ABS) { if (state) Loading Loading @@ -651,6 +660,8 @@ gpio_keys_get_devtree_pdata(struct device *dev) pdata->nbuttons = nbuttons; pdata->rep = !!of_get_property(node, "autorepeat", NULL); pdata->name = of_get_property(node, "input-name", NULL); pdata->use_syscore = of_property_read_bool(node, "use-syscore"); i = 0; for_each_child_of_node(node, pp) { Loading Loading @@ -749,6 +760,7 @@ static int gpio_keys_probe(struct platform_device *pdev) return -ENOMEM; } global_dev = dev; ddata->pdata = pdata; ddata->input = input; mutex_init(&ddata->disable_lock); Loading Loading @@ -817,6 +829,11 @@ static int gpio_keys_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, wakeup); if (pdata->use_syscore) gpio_keys_syscore_pm_ops.resume = gpio_keys_syscore_resume; register_syscore_ops(&gpio_keys_syscore_pm_ops); return 0; err_remove_group: Loading @@ -839,6 +856,7 @@ err_setup_key: static int gpio_keys_remove(struct platform_device *pdev) { sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); unregister_syscore_ops(&gpio_keys_syscore_pm_ops); device_init_wakeup(&pdev->dev, 0); Loading @@ -846,6 +864,41 @@ static int gpio_keys_remove(struct platform_device *pdev) } #ifdef CONFIG_PM_SLEEP static void gpio_keys_syscore_resume(void) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(global_dev); struct input_dev *input = ddata->input; struct gpio_button_data *bdata = NULL; int error = 0; int i; if (ddata->key_pinctrl) { error = gpio_keys_pinctrl_configure(ddata, true); if (error) { dev_err(global_dev, "failed to put the pin in resume state\n"); return; } } if (device_may_wakeup(global_dev)) { for (i = 0; i < ddata->pdata->nbuttons; i++) { bdata = &ddata->data[i]; if (bdata->button->wakeup) disable_irq_wake(bdata->irq); } } else { mutex_lock(&input->mutex); if (input->users) error = gpio_keys_open(input); mutex_unlock(&input->mutex); } if (error) return; gpio_keys_report_state(ddata); } static int gpio_keys_suspend(struct device *dev) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); Loading Loading @@ -883,6 +936,11 @@ static int gpio_keys_resume(struct device *dev) int error = 0; int i; if (ddata->pdata->use_syscore == true) { dev_dbg(global_dev, "Using syscore resume, no need of this resume.\n"); return 0; } if (ddata->key_pinctrl) { error = gpio_keys_pinctrl_configure(ddata, true); if (error) { Loading Loading @@ -910,6 +968,21 @@ static int gpio_keys_resume(struct device *dev) gpio_keys_report_state(ddata); return 0; } #else static void gpio_keys_syscore_resume(void){} static int gpio_keys_suspend(struct device *dev) { return 0; } static int gpio_keys_resume(struct device *dev) { return 0; } #endif static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); Loading
include/linux/gpio_keys.h +2 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,8 @@ struct gpio_keys_platform_data { unsigned int rep:1; int (*enable)(struct device *dev); void (*disable)(struct device *dev); const char *name; const char *name; /* input device name */ bool use_syscore; }; #endif