From patchwork Sun Aug 17 06:04:16 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 4730761 Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C9E79C0338 for ; Sun, 17 Aug 2014 06:07:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CBF5A20154 for ; Sun, 17 Aug 2014 06:07:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 86B6E201EF for ; Sun, 17 Aug 2014 06:07:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751256AbaHQGEm (ORCPT ); Sun, 17 Aug 2014 02:04:42 -0400 Received: from mga03.intel.com ([143.182.124.21]:19491 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750840AbaHQGE1 (ORCPT ); Sun, 17 Aug 2014 02:04:27 -0400 Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga101.ch.intel.com with ESMTP; 16 Aug 2014 23:04:26 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.01,878,1400050800"; d="scan'208";a="469518969" Received: from blue.fi.intel.com ([10.237.72.156]) by azsmga001.ch.intel.com with ESMTP; 16 Aug 2014 23:04:23 -0700 Received: by blue.fi.intel.com (Postfix, from userid 1004) id 7D05FE00A8; Sun, 17 Aug 2014 09:04:19 +0300 (EEST) From: Mika Westerberg To: Darren Hart , "Rafael J. Wysocki" Cc: Aaron Lu , Max Eliaser , Mika Westerberg , linux-acpi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags Date: Sun, 17 Aug 2014 09:04:16 +0300 Message-Id: <1408255459-17625-7-git-send-email-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.1.0.rc1 In-Reply-To: <1408255459-17625-1-git-send-email-mika.westerberg@linux.intel.com> References: <1408255459-17625-1-git-send-email-mika.westerberg@linux.intel.com> Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, 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 From: Aaron Lu Add a new API to get the GPIO's description pointer and its flags for both OF based system and ACPI based system. This is useful in drivers that do not need to care about the underlying firmware interface. Signed-off-by: Aaron Lu Signed-off-by: Max Eliaser Signed-off-by: Darren Hart Signed-off-by: Rafael J. Wysocki Signed-off-by: Mika Westerberg --- drivers/gpio/gpiolib-acpi.c | 81 ++++++++++++++++++++++++++++++++----------- drivers/gpio/gpiolib.c | 18 ++++++++++ drivers/gpio/gpiolib.h | 8 +++++ include/linux/gpio/consumer.h | 11 ++++++ 4 files changed, 97 insertions(+), 21 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 4a987917c186..f35e88d29a47 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -293,11 +293,38 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; lookup->info.active_low = agpio->polarity == ACPI_ACTIVE_LOW; + lookup->info.pin_config = agpio->pin_config; } return 1; } +static struct gpio_desc * +__acpi_get_gpiod_by_index(struct acpi_device *adev, int index, + struct acpi_gpio_info *info) +{ + struct acpi_gpio_lookup lookup; + struct list_head resource_list; + int ret; + + memset(&lookup, 0, sizeof(lookup)); + lookup.index = index; + + INIT_LIST_HEAD(&resource_list); + ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, + &lookup); + if (ret < 0) + return ERR_PTR(ret); + + acpi_dev_free_resource_list(&resource_list); + + if (lookup.desc && info) + *info = lookup.info; + + return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); +} + + /** * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources * @dev: pointer to a device to get GPIO from @@ -318,34 +345,46 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, struct acpi_gpio_info *info) { - struct acpi_gpio_lookup lookup; - struct list_head resource_list; - struct acpi_device *adev; - acpi_handle handle; - int ret; - - if (!dev) + if (!dev || !ACPI_COMPANION(dev)) return ERR_PTR(-EINVAL); + return __acpi_get_gpiod_by_index(ACPI_COMPANION(dev), index, info); +} - handle = ACPI_HANDLE(dev); - if (!handle || acpi_bus_get_device(handle, &adev)) - return ERR_PTR(-ENODEV); - - memset(&lookup, 0, sizeof(lookup)); - lookup.index = index; +struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int idx, + enum gpio_lookup_flags *flags) +{ + struct acpi_device *adev = ACPI_COMPANION(dev); + struct acpi_reference_args args; + struct acpi_gpio_info info; + struct gpio_desc *desc; + bool active_low; + int ret; - INIT_LIST_HEAD(&resource_list); - ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, - &lookup); - if (ret < 0) + ret = acpi_dev_get_property_reference(adev, "gpios", NULL, idx, &args); + if (ret) return ERR_PTR(ret); - acpi_dev_free_resource_list(&resource_list); + desc = __acpi_get_gpiod_by_index(args.adev, args.args[0], &info); + if (IS_ERR(desc)) + return desc; - if (lookup.desc && info) - *info = lookup.info; + /* + * The 3rd argument optionally specifies the pin polarity. We + * use that if it exists, otherwise we resort to the pin config. + * (Note that the first element of the "gpios" package goes into + * arg.adev, not args.args.) + */ + if (args.nargs >= 3) + active_low = !!args.args[2]; + else if (info.gpioint) + active_low = !!info.active_low; + else + active_low = !!(info.pin_config & ACPI_PIN_CONFIG_PULLUP); - return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); + if (active_low) + *flags |= GPIO_ACTIVE_LOW; + + return desc; } static acpi_status diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2ebc9071e354..e6c2413a6fbf 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -2644,6 +2644,24 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, return desc; } +struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx, + enum gpio_lookup_flags *flags) +{ + struct gpio_desc *desc = ERR_PTR(-ENOENT); + + if (!dev || !flags) + return ERR_PTR(-EINVAL); + + /* Using device tree? */ + if (IS_ENABLED(CONFIG_OF) && dev->of_node) + desc = of_find_gpio(dev, NULL, idx, flags); + else if (IS_ENABLED(CONFIG_ACPI) && ACPI_COMPANION(dev)) + desc = acpi_get_gpiod_flags(dev, idx, flags); + + return desc; +} +EXPORT_SYMBOL(dev_get_gpiod_flags); + static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) { const char *dev_id = dev ? dev_name(dev) : NULL; diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 1a4103dd38df..a759db968e51 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -25,6 +25,7 @@ enum of_gpio_flags; struct acpi_gpio_info { bool gpioint; bool active_low; + u8 pin_config; }; #ifdef CONFIG_ACPI @@ -33,6 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip); struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, struct acpi_gpio_info *info); +struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index, + enum gpio_lookup_flags *flags); #else static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } @@ -43,6 +46,11 @@ acpi_get_gpiod_by_index(struct device *dev, int index, { return ERR_PTR(-ENOSYS); } +static struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index, + enum gpio_lookup_flags *flags) +{ + return ERR_PTR(-ENOSYS); +} #endif int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label); diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 05e53ccb708b..53f422e4f0c9 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -7,6 +7,8 @@ struct device; +enum gpio_lookup_flags; + /** * Opaque descriptor for a GPIO. These are obtained using gpiod_get() and are * preferable to the old integer-based handles. @@ -73,6 +75,9 @@ int gpiod_to_irq(const struct gpio_desc *desc); struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); +struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx, + enum gpio_lookup_flags *flags); + #else /* CONFIG_GPIOLIB */ static inline struct gpio_desc *__must_check gpiod_get(struct device *dev, @@ -254,6 +259,12 @@ static inline int desc_to_gpio(const struct gpio_desc *desc) return -EINVAL; } +static inline struct gpio_desc *dev_get_gpiod_flags(struct device *dev, + unsigned int idx, enum gpio_lookup_flags *flags) +{ + return ERR_PTR(-ENOSYS); +} + #endif /* CONFIG_GPIOLIB */