From patchwork Tue Jul 14 08:29:54 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomeu Vizoso X-Patchwork-Id: 494934 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 8DF501402D7 for ; Tue, 14 Jul 2015 18:32:21 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=QKCf38vc; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753355AbbGNIcU (ORCPT ); Tue, 14 Jul 2015 04:32:20 -0400 Received: from mail-wg0-f52.google.com ([74.125.82.52]:34312 "EHLO mail-wg0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752619AbbGNIbN (ORCPT ); Tue, 14 Jul 2015 04:31:13 -0400 Received: by wgkl9 with SMTP id l9so2633441wgk.1; Tue, 14 Jul 2015 01:31:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=dA/jXHl1P/9uAu0o+vmgYCQOmTWiA8833FjWMTWoSHk=; b=QKCf38vc0rG/w6Q67UIqOAqmY0CkEfRu0GbzLfo31lRwsntuagZUdwozTG7Q1WxBGd prKYZtbag1MJ9SmBxfrzbteNRJ+X0D8NK/6BWlFW5s6EMmRsO9dPPiOf2wIHu2OunFaH 0XQJAs5v58Hvda2rtriRc9MWJTDsGy3lCEV06ku5250t909LUAaKSaPdJR61xa2sSl8G s6jgvKTRsUV7j5BFRYwRix+x6RXgBlY3+NWUwT8yYtsAil527num0Lcz52rjru3HTMXq yy1Zd7WGTj7/wCA6aD1/VSSUGBtr7469Yg/X2BM028tYI/ghFRvASXiTtd/GWzaaRvGS dISQ== X-Received: by 10.194.238.193 with SMTP id vm1mr73603179wjc.57.1436862671800; Tue, 14 Jul 2015 01:31:11 -0700 (PDT) Received: from cizrna.lan ([109.72.12.162]) by smtp.gmail.com with ESMTPSA id k2sm1810368wif.4.2015.07.14.01.31.10 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 14 Jul 2015 01:31:11 -0700 (PDT) From: Tomeu Vizoso To: linux-kernel@vger.kernel.org Cc: linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-tegra@vger.kernel.org, Tomeu Vizoso , Linus Walleij , Grant Likely , Rob Herring , Alexandre Courbot Subject: [PATCH v2 1/3] gpio: defer probe if pinctrl cannot be found Date: Tue, 14 Jul 2015 10:29:54 +0200 Message-Id: <1436862596-27730-2-git-send-email-tomeu.vizoso@collabora.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1436862596-27730-1-git-send-email-tomeu.vizoso@collabora.com> References: <1436862596-27730-1-git-send-email-tomeu.vizoso@collabora.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org When an OF node has a pin range for its GPIOs, return -EPROBE_DEFER if the pin controller isn't available. Otherwise, the GPIO range wouldn't be set at all unless the pin controller probed always before the GPIO chip. With this change, the probe of the GPIO chip will be deferred and will be retried at a later point, hopefully once the pin controller has been registered and probed already. Signed-off-by: Tomeu Vizoso --- Changes in v2: - Don't defer probe if the pinctrl node is disabled drivers/gpio/gpiolib-of.c | 27 ++++++++++++++++++--------- drivers/gpio/gpiolib.c | 5 ++++- include/linux/of_gpio.h | 4 ++-- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 9a0ec48a4737..4e1f73b9136a 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -338,7 +338,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) EXPORT_SYMBOL(of_mm_gpiochip_remove); #ifdef CONFIG_PINCTRL -static void of_gpiochip_add_pin_range(struct gpio_chip *chip) +static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { struct device_node *np = chip->of_node; struct of_phandle_args pinspec; @@ -349,7 +349,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) struct property *group_names; if (!np) - return; + return 0; group_names = of_find_property(np, group_names_propname, NULL); @@ -361,7 +361,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) pctldev = of_pinctrl_get(pinspec.np); if (!pctldev) - break; + return -EPROBE_DEFER; if (pinspec.args[2]) { if (group_names) { @@ -381,7 +381,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) pinspec.args[1], pinspec.args[2]); if (ret) - break; + return ret; } else { /* npins == 0: special range */ if (pinspec.args[1]) { @@ -411,32 +411,41 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) ret = gpiochip_add_pingroup_range(chip, pctldev, pinspec.args[0], name); if (ret) - break; + return ret; } } + + return 0; } #else -static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {} +static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; } #endif -void of_gpiochip_add(struct gpio_chip *chip) +int of_gpiochip_add(struct gpio_chip *chip) { + int status; + if ((!chip->of_node) && (chip->dev)) chip->of_node = chip->dev->of_node; if (!chip->of_node) - return; + return 0; if (!chip->of_xlate) { chip->of_gpio_n_cells = 2; chip->of_xlate = of_gpio_simple_xlate; } - of_gpiochip_add_pin_range(chip); + status = of_gpiochip_add_pin_range(chip); + if (status) + return status; + of_node_get(chip->of_node); of_gpiochip_scan_hogs(chip); + + return 0; } void of_gpiochip_remove(struct gpio_chip *chip) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index bf4bd1d120c3..a8cab335c0cc 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -287,7 +287,10 @@ int gpiochip_add(struct gpio_chip *chip) INIT_LIST_HEAD(&chip->pin_ranges); #endif - of_gpiochip_add(chip); + status = of_gpiochip_add(chip); + if (status) + goto err_remove_chip; + acpi_gpiochip_add(chip); status = gpiochip_sysfs_register(chip); diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index 69dbe312b11b..f3191828f037 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -54,7 +54,7 @@ extern int of_mm_gpiochip_add(struct device_node *np, struct of_mm_gpio_chip *mm_gc); extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc); -extern void of_gpiochip_add(struct gpio_chip *gc); +extern int of_gpiochip_add(struct gpio_chip *gc); extern void of_gpiochip_remove(struct gpio_chip *gc); extern int of_gpio_simple_xlate(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, @@ -76,7 +76,7 @@ static inline int of_gpio_simple_xlate(struct gpio_chip *gc, return -ENOSYS; } -static inline void of_gpiochip_add(struct gpio_chip *gc) { } +static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; } static inline void of_gpiochip_remove(struct gpio_chip *gc) { } #endif /* CONFIG_OF_GPIO */