Loading Documentation/devicetree/bindings/gpio/gpio_keys.txt 0 → 100644 +49 −0 Original line number Original line Diff line number Diff line Device-Tree bindings for input/gpio_keys.c keyboard driver Required properties: - compatible = "gpio-keys"; Optional properties: - input-name: input name of the device - autorepeat: Boolean, Enable auto repeat feature of Linux input subsystem. - pinctrl-names : This should be defined if a target uses pinctrl framework. See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt. It should specify the names of the configs that pinctrl can install in drive Following are the pinctrl configs that can be installed: "gpio_ts_active" : Active configuration of pins, this should specify active 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. Each button (key) is represented as a sub-node of "gpio-keys": Subnode properties: - gpios: OF device-tree gpio specification. - label: Descriptive name of the key. - linux,code: Keycode to emit. Optional subnode-properties: - linux,input-type: Specify event type this button/key generates. If not specified defaults to <1> == EV_KEY. - debounce-interval: Debouncing interval time in milliseconds. If not specified defaults to 5. - gpio-key,wakeup: Boolean, button can wake-up the system. Example nodes: gpio_keys { compatible = "gpio-keys"; #address-cells = <1>; #size-cells = <0>; autorepeat; input-name = "gpio-keys"; pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend"; pinctrl-0 = <&gpio_key_active>; pinctrl-1 = <&gpio_key_suspend>; button@21 { label = "GPIO Key UP"; linux,code = <103>; gpios = <&gpio1 0 1>; }; drivers/input/keyboard/gpio_keys.c +88 −3 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <linux/of_platform.h> #include <linux/of_platform.h> #include <linux/of_gpio.h> #include <linux/of_gpio.h> #include <linux/spinlock.h> #include <linux/spinlock.h> #include <linux/pinctrl/consumer.h> struct gpio_button_data { struct gpio_button_data { const struct gpio_keys_button *button; const struct gpio_keys_button *button; Loading @@ -45,6 +46,7 @@ struct gpio_button_data { struct gpio_keys_drvdata { struct gpio_keys_drvdata { const struct gpio_keys_platform_data *pdata; const struct gpio_keys_platform_data *pdata; struct pinctrl *key_pinctrl; struct input_dev *input; struct input_dev *input; struct mutex disable_lock; struct mutex disable_lock; struct gpio_button_data data[0]; struct gpio_button_data data[0]; Loading Loading @@ -551,6 +553,41 @@ static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) input_sync(input); input_sync(input); } } static int gpio_keys_pinctrl_configure(struct gpio_keys_drvdata *ddata, bool active) { struct pinctrl_state *set_state; int retval; if (active) { set_state = pinctrl_lookup_state(ddata->key_pinctrl, "tlmm_gpio_key_active"); if (IS_ERR(set_state)) { dev_err(&ddata->input->dev, "cannot get ts pinctrl active state\n"); return PTR_ERR(set_state); } } else { set_state = pinctrl_lookup_state(ddata->key_pinctrl, "tlmm_gpio_key_suspend"); if (IS_ERR(set_state)) { dev_err(&ddata->input->dev, "cannot get gpiokey pinctrl sleep state\n"); return PTR_ERR(set_state); } } retval = pinctrl_select_state(ddata->key_pinctrl, set_state); if (retval) { dev_err(&ddata->input->dev, "cannot set ts pinctrl active state\n"); return retval; } return 0; } static int gpio_keys_open(struct input_dev *input) static int gpio_keys_open(struct input_dev *input) { { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); struct gpio_keys_drvdata *ddata = input_get_drvdata(input); Loading Loading @@ -690,6 +727,7 @@ static int gpio_keys_probe(struct platform_device *pdev) size_t size; size_t size; int i, error; int i, error; int wakeup = 0; int wakeup = 0; struct pinctrl_state *set_state; if (!pdata) { if (!pdata) { pdata = gpio_keys_get_devtree_pdata(dev); pdata = gpio_keys_get_devtree_pdata(dev); Loading Loading @@ -733,13 +771,31 @@ static int gpio_keys_probe(struct platform_device *pdev) if (pdata->rep) if (pdata->rep) __set_bit(EV_REP, input->evbit); __set_bit(EV_REP, input->evbit); /* Get pinctrl if target uses pinctrl */ ddata->key_pinctrl = devm_pinctrl_get(dev); if (IS_ERR(ddata->key_pinctrl)) { if (PTR_ERR(ddata->key_pinctrl) == -EPROBE_DEFER) return -EPROBE_DEFER; pr_debug("Target does not use pinctrl\n"); ddata->key_pinctrl = NULL; } if (ddata->key_pinctrl) { error = gpio_keys_pinctrl_configure(ddata, true); if (error) { dev_err(dev, "cannot set ts pinctrl active state\n"); return error; } } for (i = 0; i < pdata->nbuttons; i++) { for (i = 0; i < pdata->nbuttons; i++) { const struct gpio_keys_button *button = &pdata->buttons[i]; const struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_button_data *bdata = &ddata->data[i]; struct gpio_button_data *bdata = &ddata->data[i]; error = gpio_keys_setup_key(pdev, input, bdata, button); error = gpio_keys_setup_key(pdev, input, bdata, button); if (error) if (error) return error; goto err_setup_key; if (button->wakeup) if (button->wakeup) wakeup = 1; wakeup = 1; Loading @@ -749,7 +805,7 @@ static int gpio_keys_probe(struct platform_device *pdev) if (error) { if (error) { dev_err(dev, "Unable to export keys/switches, error: %d\n", dev_err(dev, "Unable to export keys/switches, error: %d\n", error); error); return error; goto err_create_sysfs; } } error = input_register_device(input); error = input_register_device(input); Loading @@ -765,6 +821,18 @@ static int gpio_keys_probe(struct platform_device *pdev) err_remove_group: err_remove_group: sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); err_create_sysfs: err_setup_key: if (ddata->key_pinctrl) { set_state = pinctrl_lookup_state(ddata->key_pinctrl, "tlmm_gpio_key_suspend"); if (IS_ERR(set_state)) dev_err(dev, "cannot get gpiokey pinctrl sleep state\n"); else pinctrl_select_state(ddata->key_pinctrl, set_state); } return error; return error; } } Loading @@ -782,7 +850,7 @@ static int gpio_keys_suspend(struct device *dev) { { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); struct input_dev *input = ddata->input; struct input_dev *input = ddata->input; int i; int i, ret; if (device_may_wakeup(dev)) { if (device_may_wakeup(dev)) { for (i = 0; i < ddata->pdata->nbuttons; i++) { for (i = 0; i < ddata->pdata->nbuttons; i++) { Loading @@ -797,6 +865,14 @@ static int gpio_keys_suspend(struct device *dev) mutex_unlock(&input->mutex); mutex_unlock(&input->mutex); } } if (ddata->key_pinctrl) { ret = gpio_keys_pinctrl_configure(ddata, false); if (ret) { dev_err(dev, "failed to put the pin in suspend state\n"); return ret; } } return 0; return 0; } } Loading @@ -823,6 +899,15 @@ static int gpio_keys_resume(struct device *dev) if (error) if (error) return error; return error; if (ddata->key_pinctrl) { error = gpio_keys_pinctrl_configure(ddata, true); if (error) { dev_err(dev, "failed to put the pin in resume state\n"); return error; } } gpio_keys_report_state(ddata); gpio_keys_report_state(ddata); return 0; return 0; } } Loading Loading
Documentation/devicetree/bindings/gpio/gpio_keys.txt 0 → 100644 +49 −0 Original line number Original line Diff line number Diff line Device-Tree bindings for input/gpio_keys.c keyboard driver Required properties: - compatible = "gpio-keys"; Optional properties: - input-name: input name of the device - autorepeat: Boolean, Enable auto repeat feature of Linux input subsystem. - pinctrl-names : This should be defined if a target uses pinctrl framework. See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt. It should specify the names of the configs that pinctrl can install in drive Following are the pinctrl configs that can be installed: "gpio_ts_active" : Active configuration of pins, this should specify active 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. Each button (key) is represented as a sub-node of "gpio-keys": Subnode properties: - gpios: OF device-tree gpio specification. - label: Descriptive name of the key. - linux,code: Keycode to emit. Optional subnode-properties: - linux,input-type: Specify event type this button/key generates. If not specified defaults to <1> == EV_KEY. - debounce-interval: Debouncing interval time in milliseconds. If not specified defaults to 5. - gpio-key,wakeup: Boolean, button can wake-up the system. Example nodes: gpio_keys { compatible = "gpio-keys"; #address-cells = <1>; #size-cells = <0>; autorepeat; input-name = "gpio-keys"; pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend"; pinctrl-0 = <&gpio_key_active>; pinctrl-1 = <&gpio_key_suspend>; button@21 { label = "GPIO Key UP"; linux,code = <103>; gpios = <&gpio1 0 1>; };
drivers/input/keyboard/gpio_keys.c +88 −3 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include <linux/of_platform.h> #include <linux/of_platform.h> #include <linux/of_gpio.h> #include <linux/of_gpio.h> #include <linux/spinlock.h> #include <linux/spinlock.h> #include <linux/pinctrl/consumer.h> struct gpio_button_data { struct gpio_button_data { const struct gpio_keys_button *button; const struct gpio_keys_button *button; Loading @@ -45,6 +46,7 @@ struct gpio_button_data { struct gpio_keys_drvdata { struct gpio_keys_drvdata { const struct gpio_keys_platform_data *pdata; const struct gpio_keys_platform_data *pdata; struct pinctrl *key_pinctrl; struct input_dev *input; struct input_dev *input; struct mutex disable_lock; struct mutex disable_lock; struct gpio_button_data data[0]; struct gpio_button_data data[0]; Loading Loading @@ -551,6 +553,41 @@ static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) input_sync(input); input_sync(input); } } static int gpio_keys_pinctrl_configure(struct gpio_keys_drvdata *ddata, bool active) { struct pinctrl_state *set_state; int retval; if (active) { set_state = pinctrl_lookup_state(ddata->key_pinctrl, "tlmm_gpio_key_active"); if (IS_ERR(set_state)) { dev_err(&ddata->input->dev, "cannot get ts pinctrl active state\n"); return PTR_ERR(set_state); } } else { set_state = pinctrl_lookup_state(ddata->key_pinctrl, "tlmm_gpio_key_suspend"); if (IS_ERR(set_state)) { dev_err(&ddata->input->dev, "cannot get gpiokey pinctrl sleep state\n"); return PTR_ERR(set_state); } } retval = pinctrl_select_state(ddata->key_pinctrl, set_state); if (retval) { dev_err(&ddata->input->dev, "cannot set ts pinctrl active state\n"); return retval; } return 0; } static int gpio_keys_open(struct input_dev *input) static int gpio_keys_open(struct input_dev *input) { { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); struct gpio_keys_drvdata *ddata = input_get_drvdata(input); Loading Loading @@ -690,6 +727,7 @@ static int gpio_keys_probe(struct platform_device *pdev) size_t size; size_t size; int i, error; int i, error; int wakeup = 0; int wakeup = 0; struct pinctrl_state *set_state; if (!pdata) { if (!pdata) { pdata = gpio_keys_get_devtree_pdata(dev); pdata = gpio_keys_get_devtree_pdata(dev); Loading Loading @@ -733,13 +771,31 @@ static int gpio_keys_probe(struct platform_device *pdev) if (pdata->rep) if (pdata->rep) __set_bit(EV_REP, input->evbit); __set_bit(EV_REP, input->evbit); /* Get pinctrl if target uses pinctrl */ ddata->key_pinctrl = devm_pinctrl_get(dev); if (IS_ERR(ddata->key_pinctrl)) { if (PTR_ERR(ddata->key_pinctrl) == -EPROBE_DEFER) return -EPROBE_DEFER; pr_debug("Target does not use pinctrl\n"); ddata->key_pinctrl = NULL; } if (ddata->key_pinctrl) { error = gpio_keys_pinctrl_configure(ddata, true); if (error) { dev_err(dev, "cannot set ts pinctrl active state\n"); return error; } } for (i = 0; i < pdata->nbuttons; i++) { for (i = 0; i < pdata->nbuttons; i++) { const struct gpio_keys_button *button = &pdata->buttons[i]; const struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_button_data *bdata = &ddata->data[i]; struct gpio_button_data *bdata = &ddata->data[i]; error = gpio_keys_setup_key(pdev, input, bdata, button); error = gpio_keys_setup_key(pdev, input, bdata, button); if (error) if (error) return error; goto err_setup_key; if (button->wakeup) if (button->wakeup) wakeup = 1; wakeup = 1; Loading @@ -749,7 +805,7 @@ static int gpio_keys_probe(struct platform_device *pdev) if (error) { if (error) { dev_err(dev, "Unable to export keys/switches, error: %d\n", dev_err(dev, "Unable to export keys/switches, error: %d\n", error); error); return error; goto err_create_sysfs; } } error = input_register_device(input); error = input_register_device(input); Loading @@ -765,6 +821,18 @@ static int gpio_keys_probe(struct platform_device *pdev) err_remove_group: err_remove_group: sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); err_create_sysfs: err_setup_key: if (ddata->key_pinctrl) { set_state = pinctrl_lookup_state(ddata->key_pinctrl, "tlmm_gpio_key_suspend"); if (IS_ERR(set_state)) dev_err(dev, "cannot get gpiokey pinctrl sleep state\n"); else pinctrl_select_state(ddata->key_pinctrl, set_state); } return error; return error; } } Loading @@ -782,7 +850,7 @@ static int gpio_keys_suspend(struct device *dev) { { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); struct input_dev *input = ddata->input; struct input_dev *input = ddata->input; int i; int i, ret; if (device_may_wakeup(dev)) { if (device_may_wakeup(dev)) { for (i = 0; i < ddata->pdata->nbuttons; i++) { for (i = 0; i < ddata->pdata->nbuttons; i++) { Loading @@ -797,6 +865,14 @@ static int gpio_keys_suspend(struct device *dev) mutex_unlock(&input->mutex); mutex_unlock(&input->mutex); } } if (ddata->key_pinctrl) { ret = gpio_keys_pinctrl_configure(ddata, false); if (ret) { dev_err(dev, "failed to put the pin in suspend state\n"); return ret; } } return 0; return 0; } } Loading @@ -823,6 +899,15 @@ static int gpio_keys_resume(struct device *dev) if (error) if (error) return error; return error; if (ddata->key_pinctrl) { error = gpio_keys_pinctrl_configure(ddata, true); if (error) { dev_err(dev, "failed to put the pin in resume state\n"); return error; } } gpio_keys_report_state(ddata); gpio_keys_report_state(ddata); return 0; return 0; } } Loading