From patchwork Mon Dec 26 20:18:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 89033 Delivered-To: patch@linaro.org Received: by 10.140.20.101 with SMTP id 92csp4683110qgi; Mon, 26 Dec 2016 12:19:14 -0800 (PST) X-Received: by 10.84.241.141 with SMTP id b13mr59899951pll.28.1482783554137; Mon, 26 Dec 2016 12:19:14 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u1si34272153plj.295.2016.12.26.12.19.13; Mon, 26 Dec 2016 12:19:14 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754916AbcLZUTD (ORCPT + 25 others); Mon, 26 Dec 2016 15:19:03 -0500 Received: from mail-wm0-f46.google.com ([74.125.82.46]:36838 "EHLO mail-wm0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751292AbcLZUTC (ORCPT ); Mon, 26 Dec 2016 15:19:02 -0500 Received: by mail-wm0-f46.google.com with SMTP id c85so64358350wmi.1 for ; Mon, 26 Dec 2016 12:19:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=SEJ+qEwLYVLUzXJSrrjQipXrnOUc4kIux/mkfALy9lU=; b=EFpuhydT73varf9pOfuFs8sHCwbWp2OgnvPfRNMis4Jjd77NhrLFZMuDD8JJNJtELb SCDEv4qcN4JIhiOA7bRWedUybDbL5TmBCTEEaqBCV7BCe0vsGYIbO6DLAtVqgKOZNcf/ tNTA7HA6IhiVHvECjAysmQuUhigxI2W9wAIbc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=SEJ+qEwLYVLUzXJSrrjQipXrnOUc4kIux/mkfALy9lU=; b=CX342U/qJanFsbngbeEa4AcQgLSnSPpwKIszatV2Q2szCvdBM/eoVWu9BorZlu9KBK 4s5P6jOtrqHTWMgcvlRMr3JASEhYG2kxa+vKUZWz2i5eMfqq7IHRFdmwV9+hgklpf1Ig Wih9vU/6ZxPlhuQDbt30rD1oRpSoM2saBVbb/h/Z9rBdE0P9fX/sBe/9avDYEeJjQS0u JIt+iWdv8Ce/JZFqsup9QXGRMq7/mRIgTTfXXuYaNs5+2J+HG9VkRkRsAglVmpjIxhva yog86GUNjKAeTAOajKMgLgGUqAs7XsW+ff3fhnCb0PBa46NfEZnp557DRoji3XSMD2YU Hp0A== X-Gm-Message-State: AIkVDXIAUbV0cw4Uq/OBrGPNQFRPsuHRXqG1RWeN8PtIpmhMJviijTCYF1Zo/1+yBfHz+YRt X-Received: by 10.28.184.88 with SMTP id i85mr23737478wmf.49.1482783540169; Mon, 26 Dec 2016 12:19:00 -0800 (PST) Received: from gnarp.local (catv-80-98-18-187.catv.broadband.hu. [80.98.18.187]) by smtp.gmail.com with ESMTPSA id c81sm52697735wmf.22.2016.12.26.12.18.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Dec 2016 12:18:59 -0800 (PST) From: Linus Walleij To: Sebastian Reichel , Dmitry Eremin-Solenikov , linux-kernel@vger.kernel.org, Lars-Peter Clausen Cc: David Woodhouse , Linus Walleij , Heiko Stuebner Subject: [PATCH RESEND] power: gpio_charger: switch to using GPIO descriptors Date: Mon, 26 Dec 2016 21:18:55 +0100 Message-Id: <20161226201855.25298-1-linus.walleij@linaro.org> X-Mailer: git-send-email 2.9.3 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The GPIO charger is using a mix of the legacy GPIO interface and which is not the modern way to use GPIOs. Refactor like this: - Use a GPIO descriptor for the GPIO line used to monitor the charger. - Fetch the descriptor with devm_gpiod_get() as the first method. - If this fails and we are *not* using device tree, then start looking to see if we can use platform data instead. - After looking up and requesting a GPIO number with the legacy API, convert it to a descriptor. This way we can later isolate and drop the legacy code as more platforms move over to using descriptors. Cc: Dmitry Eremin-Solenikov Cc: Heiko Stuebner Cc: Lars-Peter Clausen Signed-off-by: Linus Walleij --- Apparently I promised to send this after v4.9-rc1 but I totally forgot about about it so now it is after v4.10-rc1. --- drivers/power/supply/gpio-charger.c | 84 ++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 34 deletions(-) -- 2.9.3 diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c index c5869b1941ac..001731e88718 100644 --- a/drivers/power/supply/gpio-charger.c +++ b/drivers/power/supply/gpio-charger.c @@ -14,7 +14,7 @@ */ #include -#include +#include /* For legacy platform data */ #include #include #include @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include @@ -34,6 +34,8 @@ struct gpio_charger { struct power_supply *charger; struct power_supply_desc charger_desc; + struct gpio_desc *gpiod; + bool legacy_gpio_requested; }; static irqreturn_t gpio_charger_irq(int irq, void *devid) @@ -58,7 +60,8 @@ static int gpio_charger_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_ONLINE: - val->intval = !!gpio_get_value_cansleep(pdata->gpio); + val->intval = gpiod_get_value_cansleep(gpio_charger->gpiod); + /* This xor is only ever used with legacy pdata GPIO */ val->intval ^= pdata->gpio_active_low; break; default: @@ -78,7 +81,6 @@ struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev) struct device_node *np = dev->of_node; struct gpio_charger_platform_data *pdata; const char *chargetype; - enum of_gpio_flags flags; int ret; if (!np) @@ -89,16 +91,6 @@ struct gpio_charger_platform_data *gpio_charger_parse_dt(struct device *dev) return ERR_PTR(-ENOMEM); pdata->name = np->name; - - pdata->gpio = of_get_gpio_flags(np, 0, &flags); - if (pdata->gpio < 0) { - if (pdata->gpio != -EPROBE_DEFER) - dev_err(dev, "could not get charger gpio\n"); - return ERR_PTR(pdata->gpio); - } - - pdata->gpio_active_low = !!(flags & OF_GPIO_ACTIVE_LOW); - pdata->type = POWER_SUPPLY_TYPE_UNKNOWN; ret = of_property_read_string(np, "charger-type", &chargetype); if (ret >= 0) { @@ -144,11 +136,6 @@ static int gpio_charger_probe(struct platform_device *pdev) } } - if (!gpio_is_valid(pdata->gpio)) { - dev_err(&pdev->dev, "Invalid gpio pin\n"); - return -EINVAL; - } - gpio_charger = devm_kzalloc(&pdev->dev, sizeof(*gpio_charger), GFP_KERNEL); if (!gpio_charger) { @@ -156,6 +143,45 @@ static int gpio_charger_probe(struct platform_device *pdev) return -ENOMEM; } + /* + * This will fetch a GPIO descriptor from device tree, ACPI or + * boardfile descriptor tables. It's good to try this first. + */ + gpio_charger->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_IN); + + /* + * If this fails and we're not using device tree, try the + * legacy platform data method. + */ + if (IS_ERR(gpio_charger->gpiod) && !pdev->dev.of_node) { + /* Non-DT: use legacy GPIO numbers */ + if (!gpio_is_valid(pdata->gpio)) { + dev_err(&pdev->dev, "Invalid gpio pin in pdata\n"); + return -EINVAL; + } + ret = gpio_request(pdata->gpio, dev_name(&pdev->dev)); + if (ret) { + dev_err(&pdev->dev, "Failed to request gpio pin: %d\n", + ret); + return ret; + } + gpio_charger->legacy_gpio_requested = true; + ret = gpio_direction_input(pdata->gpio); + if (ret) { + dev_err(&pdev->dev, "Failed to set gpio to input: %d\n", + ret); + goto err_gpio_free; + } + /* Then convert this to gpiod for now */ + gpio_charger->gpiod = gpio_to_desc(pdata->gpio); + } else if (IS_ERR(gpio_charger->gpiod)) { + /* Just try again if this happens */ + if (PTR_ERR(gpio_charger->gpiod) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_err(&pdev->dev, "error getting GPIO descriptor\n"); + return PTR_ERR(gpio_charger->gpiod); + } + charger_desc = &gpio_charger->charger_desc; charger_desc->name = pdata->name ? pdata->name : "gpio-charger"; @@ -169,17 +195,6 @@ static int gpio_charger_probe(struct platform_device *pdev) psy_cfg.of_node = pdev->dev.of_node; psy_cfg.drv_data = gpio_charger; - ret = gpio_request(pdata->gpio, dev_name(&pdev->dev)); - if (ret) { - dev_err(&pdev->dev, "Failed to request gpio pin: %d\n", ret); - goto err_free; - } - ret = gpio_direction_input(pdata->gpio); - if (ret) { - dev_err(&pdev->dev, "Failed to set gpio to input: %d\n", ret); - goto err_gpio_free; - } - gpio_charger->pdata = pdata; gpio_charger->charger = power_supply_register(&pdev->dev, @@ -191,7 +206,7 @@ static int gpio_charger_probe(struct platform_device *pdev) goto err_gpio_free; } - irq = gpio_to_irq(pdata->gpio); + irq = gpiod_to_irq(gpio_charger->gpiod); if (irq > 0) { ret = request_any_context_irq(irq, gpio_charger_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, @@ -209,8 +224,8 @@ static int gpio_charger_probe(struct platform_device *pdev) return 0; err_gpio_free: - gpio_free(pdata->gpio); -err_free: + if (gpio_charger->legacy_gpio_requested) + gpio_free(pdata->gpio); return ret; } @@ -223,7 +238,8 @@ static int gpio_charger_remove(struct platform_device *pdev) power_supply_unregister(gpio_charger->charger); - gpio_free(gpio_charger->pdata->gpio); + if (gpio_charger->legacy_gpio_requested) + gpio_free(gpio_charger->pdata->gpio); return 0; }