From patchwork Fri Sep 9 11:40:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 75883 Delivered-To: patch@linaro.org Received: by 10.140.106.11 with SMTP id d11csp298800qgf; Fri, 9 Sep 2016 04:40:20 -0700 (PDT) X-Received: by 10.66.145.73 with SMTP id ss9mr5679172pab.82.1473421220261; Fri, 09 Sep 2016 04:40:20 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b64si3615315pfk.63.2016.09.09.04.40.19; Fri, 09 Sep 2016 04:40:20 -0700 (PDT) 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 S1754166AbcIILkR (ORCPT + 27 others); Fri, 9 Sep 2016 07:40:17 -0400 Received: from mail-lf0-f49.google.com ([209.85.215.49]:36559 "EHLO mail-lf0-f49.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753017AbcIILkP (ORCPT ); Fri, 9 Sep 2016 07:40:15 -0400 Received: by mail-lf0-f49.google.com with SMTP id g62so41876939lfe.3 for ; Fri, 09 Sep 2016 04:40:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=Y2xL0fuFlq2nuthLQ7U4QUcYMxkTBroCYvhLz8tVpd0=; b=MQKOhm0N0GPhvbkndvG8zfGO9mdzxziUzGR4wXRgDobDmdDD665IZA9Qj1ALwWt3jl 1Y65C1lBeppbSZMr4HtoDR5ihvZbyaB5ON+B7Nwi/2mS798puXkjsChE1xdd/eFjIHkS SWL6gbQLM7owUipL7FH4Uqxf42UW4c6OQQhkc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=Y2xL0fuFlq2nuthLQ7U4QUcYMxkTBroCYvhLz8tVpd0=; b=b9y2Rm6yUfpqWBFo8Elq70CB38XT9sm07j4H1JcfCnIX+bcuHoYmz81hbdfpzUoGj6 vFjzl2ZBFS1pOim+y68xeanR+5gxyClamXGMotiyDmTf77FQza8cZggMUO1T80a78pDc aUMvxHQAt0J4w7Rmh9Wcl1F0Cj95y6vq9OGt3/cLA7ivg6XkBgeIpZqsCNuUfKxsl9B+ 4zJbxXbX+17HeK5pFvqduRNgN40gy/djE69129xXW2UFtGTLJPAqlzPurGHVV3e9QCer fr2sdGvhy2VJig2R/jiRDczeZ7FfOkh1sQzT72bLEUUG9+u+D9Pb7tUMf1ttJIissROI CFdQ== X-Gm-Message-State: AE9vXwPD8YamCm+xTw4oEGm0VCBL3Ygy2RdzHVklDFD/bqhovcJ5rUCBJgALk9HYkNrC7SMh X-Received: by 10.25.17.70 with SMTP id g67mr1102694lfi.51.1473421212967; Fri, 09 Sep 2016 04:40:12 -0700 (PDT) Received: from linuslaptop.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id w15sm505640lfi.16.2016.09.09.04.40.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 09 Sep 2016 04:40:12 -0700 (PDT) From: Linus Walleij To: Sebastian Reichel , Dmitry Eremin-Solenikov , linux-kernel@vger.kernel.org Cc: David Woodhouse , Linus Walleij , Heiko Stuebner , Lars-Peter Clausen Subject: [PATCH] power: gpio_charger: switch to using GPIO descriptors Date: Fri, 9 Sep 2016 13:40:04 +0200 Message-Id: <1473421204-25355-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 2.7.4 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 --- I would be very happy if some people can test this. I think only the chromebook use it from device tree, but I'm equally interested in the legacy usecase to work as nice as before. --- drivers/power/gpio-charger.c | 84 ++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 34 deletions(-) -- 2.7.4 diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index c5869b1941ac..001731e88718 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/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; }