Received: by 10.213.65.68 with SMTP id h4csp4355459imn; Tue, 10 Apr 2018 13:34:30 -0700 (PDT) X-Google-Smtp-Source: AIpwx48cqUKE7sLdnXLOU6PtM7vgo0J6Trfz1DW64A4GD8qoBGknryUktZT+guWgMfGRY/7dOajw X-Received: by 10.98.99.4 with SMTP id x4mr1551823pfb.179.1523392470897; Tue, 10 Apr 2018 13:34:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523392470; cv=none; d=google.com; s=arc-20160816; b=pFTxErZ8WU1dHWCibFa7rwmJzkXRlkHWKrMfYw0eM2udh3yF/aXzgt81WtXTbEHR9r z90WuzAOV3FCZjkz+YiFuQZ/tEoNW5Pvl9GUBnP2d3pZUrujG3sbbBGNmLginUB/r2kS IzDGwYidvpFwY7mzcmPqP/PwBJLjdKyRP8KkcEkGDPfP10EbpjuZp0vHLCf296pZhZNx WxL4M+4pPBGyvlQnkqfkUYIvYTGeV0kTq8nTdn6MkWVKRZxvBHk/t3/ZKRp6LlgjM0bU oH7/9Gmgq9crYiqjhHKTj04MnFeNp3wbf/85Uqo0yjQRZhFqKGGeTU6LlDbXag/ftfMx EdUw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=1iA6JjR9+Xj0ssL5elFvcuDsqAzqqDlolJkK7OihIYI=; b=lj40Tcziv0j2+nfL1HCqwXsXtpcn00lgnTDmv8ItJBNLcxduFNAvkdpuVE6X63DuH0 xNbH5Upo75iK14TjEVoWlt5/WYTHpZsr0xsKvX6BKwTFcYVjFrv+gX75v5y/79+tK9JM cYrA1wMtDKKEIBO9IdxnMz3jj6bJbhVx/jfo0FQQVy2Ngy/+b/Nv2iNUZA4CkI2iYOjr mLNqWd5/p04RpovMWzd3aITR56TXrkYGRTbHFJMS4fAD/G7UAVMfmGG9FbLYVClPBHsU onTrl05zFVkYWoS2bRVDMHp8zFZ6ORz2uZhbvBPcc6tjuee4vWW8eDUm34RDQxA2DDCs mHBQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@bgdev-pl.20150623.gappssmtp.com header.s=20150623 header.b=OgxQMgfO; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p24si2570341pfh.328.2018.04.10.13.33.51; Tue, 10 Apr 2018 13:34:30 -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=@bgdev-pl.20150623.gappssmtp.com header.s=20150623 header.b=OgxQMgfO; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753246AbeDJUag (ORCPT + 99 others); Tue, 10 Apr 2018 16:30:36 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:36069 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752627AbeDJUae (ORCPT ); Tue, 10 Apr 2018 16:30:34 -0400 Received: by mail-wm0-f67.google.com with SMTP id x82so25647068wmg.1 for ; Tue, 10 Apr 2018 13:30:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=1iA6JjR9+Xj0ssL5elFvcuDsqAzqqDlolJkK7OihIYI=; b=OgxQMgfObpNCRF0BIfVsETXxdmvLx/5oODkJey2YCbawIklDQdXl92yjzLckjzFFVC uOH1FON2+OPi3aQmC2JCcRff+C/SPRF+NnB3wlm+MGEvQG3QcHwLwZr7V6WWP+KdR4dD Y43vanSABQO2MCX+lEzjv8J4CSdKVTBFwAlLODoQNzx+0u/7BGEaX0LSf0D2FMW0bTwM Urwf0pAWgzJSATFR3QUB5c2xqdNCFmNS4H/q6+Q/KRARfAHVp9KIThoH0Y9PO/4c1a2u 8Z1k88WIVxtlSZQL+WRGbjedsl0eBx414JrO1FvTYc6FTHqhMbstKs6u1zv5adKyhjpE /HxA== 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=1iA6JjR9+Xj0ssL5elFvcuDsqAzqqDlolJkK7OihIYI=; b=MsUmw4NcOiSIkQcLUuBF2fKYppJWxbl9djp0BOVw2PgGspzjHe9COe7D8oWl9co/+u k7msQha4N/yjp6RYcUukmBUtwysbZumPL/3/s/zeuqZNriAYQxbvSuhQDdgcQdmfW86W jNLFzEFlTnRyeIBBErLI3jQemsnthy9FjvqL2iXKG48cMkpTOSAfZQAvu5GDGSwo1Mul Xp4hOCaTkaL1O08/6wUS30qwlwS33PpFb2iT2DVU3LbeDIRCxUbfhMp32pP7+q9RNfsY m+hy3TNeVS9HoDbrlrJzzkp4ADNZ+2EYvdybxzSWXUmSmCNF1RftC6duWaQTXPYd4+5a 7LlQ== X-Gm-Message-State: ALQs6tAhVtWSVTmhYc8MZxeQg0pvn6pD8+xp25MftnoP5pGo7law4zHI sVrGm4cZdrrEVjAOEqbO9mNoHHQmDxc= X-Received: by 10.28.32.210 with SMTP id g201mr657601wmg.9.1523392233171; Tue, 10 Apr 2018 13:30:33 -0700 (PDT) Received: from brgl-bgdev.home ([2a01:cb1d:af:5b00:e837:b8d5:48c1:571b]) by smtp.gmail.com with ESMTPSA id j8sm764309wri.22.2018.04.10.13.30.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 10 Apr 2018 13:30:32 -0700 (PDT) From: Bartosz Golaszewski To: Linus Walleij , Jonathan Corbet Cc: linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Bartosz Golaszewski Subject: [PATCH v2] gpiolib: add hogs support for machine code Date: Tue, 10 Apr 2018 22:30:28 +0200 Message-Id: <20180410203028.11412-1-brgl@bgdev.pl> X-Mailer: git-send-email 2.17.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Board files constitute a significant part of the users of the legacy GPIO framework. In many cases they only export a line and set its desired value. We could use GPIO hogs for that like we do for DT and ACPI but there's no support for that in machine code. This patch proposes to extend the machine.h API with support for registering hog tables in board files. Signed-off-by: Bartosz Golaszewski --- v1 -> v2: - kbuild bot complains about enum gpiod_flags having incomplete type although it builds fine for me locally: change the type of dflags to int Documentation/driver-api/gpio/board.rst | 16 ++++++ drivers/gpio/gpiolib.c | 67 +++++++++++++++++++++++++ include/linux/gpio/machine.h | 31 ++++++++++++ 3 files changed, 114 insertions(+) diff --git a/Documentation/driver-api/gpio/board.rst b/Documentation/driver-api/gpio/board.rst index 25d62b2e9fd0..2c112553df84 100644 --- a/Documentation/driver-api/gpio/board.rst +++ b/Documentation/driver-api/gpio/board.rst @@ -177,3 +177,19 @@ mapping and is thus transparent to GPIO consumers. A set of functions such as gpiod_set_value() is available to work with the new descriptor-oriented interface. + +Boards using platform data can also hog GPIO lines by defining GPIO hog tables. + +.. code-block:: c + + struct gpiod_hog gpio_hog_table[] = { + GPIO_HOG("gpio.0", 10, "foo", GPIO_ACTIVE_LOW, GPIOD_OUT_HIGH), + { } + }; + +And the table can be added to the board code as follows:: + + gpiod_add_hogs(gpio_hog_table); + +The line will be hogged as soon as the gpiochip is created or - in case the +chip was created earlier - when the hog table is registered. diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 43aeb07343ec..547adc149b62 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -71,6 +71,9 @@ static DEFINE_MUTEX(gpio_lookup_lock); static LIST_HEAD(gpio_lookup_list); LIST_HEAD(gpio_devices); +static DEFINE_MUTEX(gpio_machine_hogs_mutex); +static LIST_HEAD(gpio_machine_hogs); + static void gpiochip_free_hogs(struct gpio_chip *chip); static int gpiochip_add_irqchip(struct gpio_chip *gpiochip, struct lock_class_key *lock_key, @@ -1171,6 +1174,41 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) return status; } +static void gpiochip_machine_hog(struct gpio_chip *chip, struct gpiod_hog *hog) +{ + struct gpio_desc *desc; + int rv; + + desc = gpiochip_get_desc(chip, hog->chip_hwnum); + if (IS_ERR(desc)) { + pr_err("%s: unable to get GPIO desc: %ld\n", + __func__, PTR_ERR(desc)); + return; + } + + if (desc->flags & FLAG_IS_HOGGED) + return; + + rv = gpiod_hog(desc, hog->line_name, hog->lflags, hog->dflags); + if (rv) + pr_err("%s: unable to hog GPIO line (%s:%u): %d\n", + __func__, chip->label, hog->chip_hwnum, rv); +} + +static void machine_gpiochip_add(struct gpio_chip *chip) +{ + struct gpiod_hog *hog; + + mutex_lock(&gpio_machine_hogs_mutex); + + list_for_each_entry(hog, &gpio_machine_hogs, list) { + if (!strcmp(chip->label, hog->chip_label)) + gpiochip_machine_hog(chip, hog); + } + + mutex_unlock(&gpio_machine_hogs_mutex); +} + static void gpiochip_setup_devs(void) { struct gpio_device *gdev; @@ -1326,6 +1364,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, acpi_gpiochip_add(chip); + machine_gpiochip_add(chip); + /* * By first adding the chardev, and then adding the device, * we get a device node entry in sysfs under @@ -3462,6 +3502,33 @@ void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) } EXPORT_SYMBOL_GPL(gpiod_remove_lookup_table); +/** + * gpiod_add_hogs() - register a set of GPIO hogs from machine code + * @hogs: table of gpio hog entries with a zeroed sentinel at the end + */ +void gpiod_add_hogs(struct gpiod_hog *hogs) +{ + struct gpio_chip *chip; + struct gpiod_hog *hog; + + mutex_lock(&gpio_machine_hogs_mutex); + + for (hog = &hogs[0]; hog->chip_label; hog++) { + list_add_tail(&hog->list, &gpio_machine_hogs); + + /* + * The chip may have been registered earlier, so check if it + * exists and, if so, try to hog the line now. + */ + chip = find_chip_by_name(hog->chip_label); + if (chip) + gpiochip_machine_hog(chip, hog); + } + + mutex_unlock(&gpio_machine_hogs_mutex); +} +EXPORT_SYMBOL_GPL(gpiod_add_hogs); + static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) { const char *dev_id = dev ? dev_name(dev) : NULL; diff --git a/include/linux/gpio/machine.h b/include/linux/gpio/machine.h index b2f2dc638463..daa44eac9241 100644 --- a/include/linux/gpio/machine.h +++ b/include/linux/gpio/machine.h @@ -39,6 +39,23 @@ struct gpiod_lookup_table { struct gpiod_lookup table[]; }; +/** + * struct gpiod_hog - GPIO line hog table + * @chip_label: name of the chip the GPIO belongs to + * @chip_hwnum: hardware number (i.e. relative to the chip) of the GPIO + * @line_name: consumer name for the hogged line + * @lflags: mask of GPIO lookup flags + * @dflags: GPIO flags used to specify the direction and value + */ +struct gpiod_hog { + struct list_head list; + const char *chip_label; + u16 chip_hwnum; + const char *line_name; + enum gpio_lookup_flags lflags; + int dflags; +}; + /* * Simple definition of a single GPIO under a con_id */ @@ -59,10 +76,23 @@ struct gpiod_lookup_table { .flags = _flags, \ } +/* + * Simple definition of a single GPIO hog in an array. + */ +#define GPIO_HOG(_chip_label, _chip_hwnum, _line_name, _lflags, _dflags) \ +{ \ + .chip_label = _chip_label, \ + .chip_hwnum = _chip_hwnum, \ + .line_name = _line_name, \ + .lflags = _lflags, \ + .dflags = _dflags, \ +} + #ifdef CONFIG_GPIOLIB void gpiod_add_lookup_table(struct gpiod_lookup_table *table); void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n); void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); +void gpiod_add_hogs(struct gpiod_hog *hogs); #else static inline void gpiod_add_lookup_table(struct gpiod_lookup_table *table) {} @@ -70,6 +100,7 @@ static inline void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n) {} static inline void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) {} +static inline void gpiod_add_hogs(struct gpiod_hog *hogs) {} #endif #endif /* __LINUX_GPIO_MACHINE_H */ -- 2.17.0