From patchwork Fri Feb 26 18:50:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 8441251 Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 5556CC0553 for ; Fri, 26 Feb 2016 18:51:00 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3B1FA20268 for ; Fri, 26 Feb 2016 18:50:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E804C20259 for ; Fri, 26 Feb 2016 18:50:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1422821AbcBZSuh (ORCPT ); Fri, 26 Feb 2016 13:50:37 -0500 Received: from mail-pa0-f41.google.com ([209.85.220.41]:33727 "EHLO mail-pa0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1422988AbcBZSuf (ORCPT ); Fri, 26 Feb 2016 13:50:35 -0500 Received: by mail-pa0-f41.google.com with SMTP id fl4so55137736pad.0; Fri, 26 Feb 2016 10:50:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :user-agent; bh=N5fSoFWXuJy36H79RPz7Lro10UwsDa1NvnOn0VgrXCw=; b=Nyqq5sK0QTCYYYEaleD0B/X9jmqBy4HjOwvntKk1Pff3wWwFu/5ZJf8ti6WpsCwKJo d/kOA14vSNGA3rVl6ZuA7z/keEsyWDRfR0OE7mwvyrw9JrsSv7KlETTwQkI2wJIdcixj 0MYJJ+pFmKZI5upWjLuD8BpONkSiK64PPmJ3dAVS0fF+haMvqIDjQKFlAhoMd+dunXcm 4rorqXANchjPi+VG3z9JmOWioifqcn67H6wqJ0SGE1RgCzeH7zEKw9gn5yRgN9qgPo2/ 0D1BsKLidFRgZanzwvzpMXWa1GbESpsmuHernTSstHazkpTi8yY1LO02r+twIDBk2Iyl Nl6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:user-agent; bh=N5fSoFWXuJy36H79RPz7Lro10UwsDa1NvnOn0VgrXCw=; b=gguX/8nQMC6nZ34WuVoXDeX/9xa5kApYwPHNc7bcG/jj58ZfTKUr96PBTUjHRnXWlq eyyHHsUMf80WCWIM2xzB62Xp2t+s40rSK8U6Z4eiFYpvJJzf7mhw+qmGvgbEz99RuE8U 1v+qczbgAKBbmurryiX3yPhJRxipkxyL6TQs+dm/riC6ISJ8czPBgiaGWd7IkxHrmY6c jdLzuo7ONVMzAeLD6L10sEJHHV2Ibn3k9D0umLhomPDDz2p8bkI7ryLMjhW+jCdLA92K 2MJfgFgkkqJr1FMySzSyZNS5bL+qyv6YjYLzM2OZBkzPWzs3NvrOiHLBbBIpY9esD34O rQpA== X-Gm-Message-State: AD7BkJLhfhoDsBkQyBm6fphmnsXqTUC1SPYQPrLq7y+eGH0OPGz3+VDQkydF9D1Ot7D5fQ== X-Received: by 10.67.1.237 with SMTP id bj13mr4312776pad.130.1456512634271; Fri, 26 Feb 2016 10:50:34 -0800 (PST) Received: from dtor-ws ([2620:0:1000:1301:d589:6701:3614:453c]) by smtp.gmail.com with ESMTPSA id p9sm20995108pfa.11.2016.02.26.10.50.33 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Fri, 26 Feb 2016 10:50:33 -0800 (PST) Date: Fri, 26 Feb 2016 10:50:31 -0800 From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: Linus Walleij , Aaron Lu , Mika Westerberg , Geert Uytterhoeven , "Rafael J. Wysocki" , linux-kernel@vger.kernel.org Subject: [PATCH] Input: gpio_keys_polled - keep button data constant Message-ID: <20160226185031.GA17815@dtor-ws> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Commit 633a21d80b4a ("input: gpio_keys_polled: Add support for GPIO descriptors") placed gpio descriptor into gpio_keys_button structure, which is supposed to be part of platform data and not modifiable by the driver. To keep the data constant, let's move the descriptor to gpio_keys_button_data structure instead. Signed-off-by: Dmitry Torokhov --- Compiled only, I do not have devices with polled keys... drivers/input/keyboard/gpio_keys_polled.c | 104 ++++++++++++++++-------------- include/linux/gpio_keys.h | 4 +- 2 files changed, 58 insertions(+), 50 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 62bdb1d..daef8ea 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -30,6 +30,7 @@ #define DRV_NAME "gpio-keys-polled" struct gpio_keys_button_data { + struct gpio_desc *gpiod; int last_state; int count; int threshold; @@ -46,7 +47,7 @@ struct gpio_keys_polled_dev { }; static void gpio_keys_button_event(struct input_polled_dev *dev, - struct gpio_keys_button *button, + const struct gpio_keys_button *button, int state) { struct gpio_keys_polled_dev *bdev = dev->private; @@ -70,15 +71,15 @@ static void gpio_keys_button_event(struct input_polled_dev *dev, } static void gpio_keys_polled_check_state(struct input_polled_dev *dev, - struct gpio_keys_button *button, + const struct gpio_keys_button *button, struct gpio_keys_button_data *bdata) { int state; if (bdata->can_sleep) - state = !!gpiod_get_value_cansleep(button->gpiod); + state = !!gpiod_get_value_cansleep(bdata->gpiod); else - state = !!gpiod_get_value(button->gpiod); + state = !!gpiod_get_value(bdata->gpiod); gpio_keys_button_event(dev, button, state); @@ -142,48 +143,35 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev) pdata->disable(bdev->dev); } -static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev) +static struct gpio_keys_platform_data * +gpio_keys_polled_get_devtree_pdata(struct device *dev) { struct gpio_keys_platform_data *pdata; struct gpio_keys_button *button; struct fwnode_handle *child; - int error; int nbuttons; nbuttons = device_get_child_node_count(dev); if (nbuttons == 0) - return NULL; + return ERR_PTR(-EINVAL); pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * sizeof(*button), GFP_KERNEL); if (!pdata) return ERR_PTR(-ENOMEM); - pdata->buttons = (struct gpio_keys_button *)(pdata + 1); + button = (struct gpio_keys_button *)(pdata + 1); + + pdata->buttons = button; + pdata->nbuttons = nbuttons; pdata->rep = device_property_present(dev, "autorepeat"); device_property_read_u32(dev, "poll-interval", &pdata->poll_interval); device_for_each_child_node(dev, child) { - struct gpio_desc *desc; - - desc = devm_get_gpiod_from_child(dev, NULL, child); - if (IS_ERR(desc)) { - error = PTR_ERR(desc); - if (error != -EPROBE_DEFER) - dev_err(dev, - "Failed to get gpio flags, error: %d\n", - error); - fwnode_handle_put(child); - return ERR_PTR(error); - } - - button = &pdata->buttons[pdata->nbuttons++]; - button->gpiod = desc; - - if (fwnode_property_read_u32(child, "linux,code", &button->code)) { - dev_err(dev, "Button without keycode: %d\n", - pdata->nbuttons - 1); + if (fwnode_property_read_u32(child, "linux,code", + &button->code)) { + dev_err(dev, "button without keycode\n"); fwnode_handle_put(child); return ERR_PTR(-EINVAL); } @@ -206,10 +194,9 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct if (fwnode_property_read_u32(child, "debounce-interval", &button->debounce_interval)) button->debounce_interval = 5; - } - if (pdata->nbuttons == 0) - return ERR_PTR(-EINVAL); + button++; + } return pdata; } @@ -220,7 +207,7 @@ static void gpio_keys_polled_set_abs_params(struct input_dev *input, int i, min = 0, max = 0; for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; + const struct gpio_keys_button *button = &pdata->buttons[i]; if (button->type != EV_ABS || button->code != code) continue; @@ -230,6 +217,7 @@ static void gpio_keys_polled_set_abs_params(struct input_dev *input, if (button->value > max) max = button->value; } + input_set_abs_params(input, code, min, max, 0, 0); } @@ -242,6 +230,7 @@ MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match); static int gpio_keys_polled_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct fwnode_handle *child = NULL; const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); struct gpio_keys_polled_dev *bdev; struct input_polled_dev *poll_dev; @@ -254,10 +243,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) pdata = gpio_keys_polled_get_devtree_pdata(dev); if (IS_ERR(pdata)) return PTR_ERR(pdata); - if (!pdata) { - dev_err(dev, "missing platform data\n"); - return -EINVAL; - } } if (!pdata->poll_interval) { @@ -300,7 +285,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) __set_bit(EV_REP, input->evbit); for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; + const struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_keys_button_data *bdata = &bdev->data[i]; unsigned int type = button->type ?: EV_KEY; @@ -309,11 +294,30 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) return -EINVAL; } - /* - * Legacy GPIO number so request the GPIO here and - * convert it to descriptor. - */ - if (!button->gpiod && gpio_is_valid(button->gpio)) { + if (!dev_get_platdata(dev)) { + /* No legacy static platform data */ + child = device_get_next_child_node(dev, child); + if (!child) { + dev_err(dev, "missing child device node\n"); + return -EINVAL; + } + + bdata->gpiod = devm_get_gpiod_from_child(dev, NULL, + child); + if (IS_ERR(bdata->gpiod)) { + error = PTR_ERR(bdata->gpiod); + if (error != -EPROBE_DEFER) + dev_err(dev, + "failed to get gpio: %d\n", + error); + fwnode_handle_put(child); + return error; + } + } else if (gpio_is_valid(button->gpio)) { + /* + * Legacy GPIO number so request the GPIO here and + * convert it to descriptor. + */ unsigned flags = GPIOF_IN; if (button->active_low) @@ -322,18 +326,22 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) error = devm_gpio_request_one(&pdev->dev, button->gpio, flags, button->desc ? : DRV_NAME); if (error) { - dev_err(dev, "unable to claim gpio %u, err=%d\n", + dev_err(dev, + "unable to claim gpio %u, err=%d\n", button->gpio, error); return error; } - button->gpiod = gpio_to_desc(button->gpio); + bdata->gpiod = gpio_to_desc(button->gpio); + if (!bdata->gpiod) { + dev_err(dev, + "unable to convert gpio %u to descriptor\n", + button->gpio); + return -EINVAL; + } } - if (IS_ERR(button->gpiod)) - return PTR_ERR(button->gpiod); - - bdata->can_sleep = gpiod_cansleep(button->gpiod); + bdata->can_sleep = gpiod_cansleep(bdata->gpiod); bdata->last_state = -1; bdata->threshold = DIV_ROUND_UP(button->debounce_interval, pdata->poll_interval); @@ -344,6 +352,8 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) button->code); } + fwnode_handle_put(child); + bdev->poll_dev = poll_dev; bdev->dev = dev; bdev->pdata = pdata; diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h index ee2d8c6..d1250ad 100644 --- a/include/linux/gpio_keys.h +++ b/include/linux/gpio_keys.h @@ -2,7 +2,6 @@ #define _GPIO_KEYS_H struct device; -struct gpio_desc; /** * struct gpio_keys_button - configuration parameters @@ -31,7 +30,6 @@ struct gpio_keys_button { bool can_disable; int value; unsigned int irq; - struct gpio_desc *gpiod; }; /** @@ -46,7 +44,7 @@ struct gpio_keys_button { * @name: input device name */ struct gpio_keys_platform_data { - struct gpio_keys_button *buttons; + const struct gpio_keys_button *buttons; int nbuttons; unsigned int poll_interval; unsigned int rep:1;