From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail-pg0-x241.google.com ([2607:f8b0:400e:c05::241]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dHLy2-0000LR-91 for barebox@lists.infradead.org; Sun, 04 Jun 2017 03:12:39 +0000 Received: by mail-pg0-x241.google.com with SMTP id f127so5970760pgc.2 for ; Sat, 03 Jun 2017 20:12:17 -0700 (PDT) From: Andrey Smirnov Date: Sat, 3 Jun 2017 20:11:53 -0700 Message-Id: <20170604031154.26663-4-andrew.smirnov@gmail.com> In-Reply-To: <20170604031154.26663-1-andrew.smirnov@gmail.com> References: <20170604031154.26663-1-andrew.smirnov@gmail.com> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "barebox" Errors-To: barebox-bounces+u.kleine-koenig=pengutronix.de@lists.infradead.org Subject: [PATCH v3 3/4] gpiolib: Add support for GPIO "hog" nodes To: barebox@lists.infradead.org Cc: Andrey Smirnov , Nikita Yushchenko , cphealy@gmail.com Add code to support 'gpio-hog' nodes used in some .dts files in Linux kernel. Cc: cphealy@gmail.com Cc: Nikita Yushchenko Signed-off-by: Andrey Smirnov --- drivers/gpio/gpiolib.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 28f6a5e..a3e17ad 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -304,6 +305,99 @@ static int gpiochip_find_base(int start, int ngpio) return base; } +static int of_hog_gpio(struct device_node *np, struct gpio_chip *chip, + unsigned int idx) +{ + struct device_node *chip_np = chip->dev->device_node; + unsigned long flags = 0; + u32 gpio_cells, gpio_num, gpio_flags; + int ret, gpio; + const char *name = NULL; + + ret = of_property_read_u32(chip_np, "#gpio-cells", &gpio_cells); + if (ret) + return ret; + + /* + * Support for GPIOs that don't have #gpio-cells set to 2 is + * not implemented + */ + if (WARN_ON(gpio_cells != 2)) + return -ENOTSUPP; + + ret = of_property_read_u32_index(np, "gpios", idx * gpio_cells, + &gpio_num); + if (ret) + return ret; + + ret = of_property_read_u32_index(np, "gpios", idx * gpio_cells + 1, + &gpio_flags); + if (ret) + return ret; + + if (gpio_flags & OF_GPIO_ACTIVE_LOW) + flags |= GPIOF_ACTIVE_LOW; + + gpio = gpio_get_num(chip->dev, gpio_num); + if (ret == -EPROBE_DEFER) + return ret; + + if (ret < 0) { + dev_err(chip->dev, "unable to get gpio %u\n", gpio_num); + return ret; + } + + + /* + * Note that, in order to be compatible with Linux, the code + * below interprets 'output-high' as to mean 'output-active'. + * That is, when processed for active-low GPIO, it will result + * in output being asserted logically 'active', but physically + * 'low'. + * + * Conversely it means that specifying 'output-low' for + * 'active-low' GPIO would result in 'high' level observed on + * the corresponding pin + * + */ + if (of_property_read_bool(np, "input")) + flags |= GPIOF_DIR_IN; + else if (of_property_read_bool(np, "output-low")) + flags |= GPIOF_OUT_INIT_INACTIVE; + else if (of_property_read_bool(np, "output-high")) + flags |= GPIOF_OUT_INIT_ACTIVE; + else + return -EINVAL; + + of_property_read_string(np, "line-name", &name); + + return gpio_request_one(gpio, flags, name); +} + +static int of_gpiochip_scan_hogs(struct gpio_chip *chip) +{ + struct device_node *np; + int ret, i; + + for_each_available_child_of_node(chip->dev->device_node, np) { + if (!of_property_read_bool(np, "gpio-hog")) + continue; + + for (ret = 0, i = 0; + !ret; + ret = of_hog_gpio(np, chip, i), i++) + ; + /* + * We ignore -EOVERFLOW because it serves us as an + * indicator that there's no more GPIOs to handle. + */ + if (ret < 0 && ret != -EOVERFLOW) + return ret; + } + + return 0; +} + int gpiochip_add(struct gpio_chip *chip) { int base, i; @@ -322,7 +416,7 @@ int gpiochip_add(struct gpio_chip *chip) for (i = chip->base; i < chip->base + chip->ngpio; i++) gpio_desc[i].chip = chip; - return 0; + return of_gpiochip_scan_hogs(chip); } void gpiochip_remove(struct gpio_chip *chip) -- 2.9.4 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox