From patchwork Fri Dec 1 23:28:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timur Tabi X-Patchwork-Id: 10088245 X-Patchwork-Delegate: agross@codeaurora.org Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BEEEE60327 for ; Fri, 1 Dec 2017 23:28:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AE1DF2A78F for ; Fri, 1 Dec 2017 23:28:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A30672A799; Fri, 1 Dec 2017 23:28:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1FA612A78F for ; Fri, 1 Dec 2017 23:28:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751667AbdLAX2e (ORCPT ); Fri, 1 Dec 2017 18:28:34 -0500 Received: from smtp.codeaurora.org ([198.145.29.96]:41728 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751414AbdLAX2c (ORCPT ); Fri, 1 Dec 2017 18:28:32 -0500 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id DE81C6083B; Fri, 1 Dec 2017 23:28:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1512170911; bh=jReswuCp7nU9Vh6v6ll+io7pQ4Q06r4qKU55fpwzl8A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ktZ5H5IJryaotuYevHWXPJt/Ug3rwn7Swi6qyBGrH4YkF3+EpSybIS9dy+Eakt/2i iC+bMJyo6fsH1SCnVIR8SUuJ4JxNr+adAfZtn737CKvYBuZC5nfcQbmWEW8b6i02U5 cwVw3DRYUnT6+xYGAtDOwP5DBMTEW+bYJZve4z3U= Received: from timur-ubuntu.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: timur@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 53F6B607F5; Fri, 1 Dec 2017 23:28:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1512170911; bh=jReswuCp7nU9Vh6v6ll+io7pQ4Q06r4qKU55fpwzl8A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ktZ5H5IJryaotuYevHWXPJt/Ug3rwn7Swi6qyBGrH4YkF3+EpSybIS9dy+Eakt/2i iC+bMJyo6fsH1SCnVIR8SUuJ4JxNr+adAfZtn737CKvYBuZC5nfcQbmWEW8b6i02U5 cwVw3DRYUnT6+xYGAtDOwP5DBMTEW+bYJZve4z3U= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 53F6B607F5 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=timur@codeaurora.org From: Timur Tabi To: linux-arm-msm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org, Linus Walleij , Andy Shevchenko , Mika Westerberg , thierry.reding@gmail.com, Stephen Boyd , david.brown@linaro.org, andy.gross@linaro.org, Bjorn Andersson , Varadarajan Narayanan , Archit Taneja Cc: timur@codeaurora.org Subject: [PATCH 2/4] [v2] gpiolib: add bitmask for valid GPIO lines Date: Fri, 1 Dec 2017 17:28:22 -0600 Message-Id: <1512170904-4749-3-git-send-email-timur@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1512170904-4749-1-git-send-email-timur@codeaurora.org> References: <1512170904-4749-1-git-send-email-timur@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add support for specifying that some GPIOs within a range are unavailable. Some systems have a sparse list of GPIOs, where a range of GPIOs is specified (usually 0 to n-1), but some subset within that range is absent or unavailable for whatever reason. To support this, allow drivers to specify a bitmask of GPIOs that are present or absent. Gpiolib will then block access to those that are absent. Signed-off-by: Timur Tabi --- drivers/gpio/gpiolib.c | 47 ++++++++++++++++++++++++++++++++++++++++++++- include/linux/gpio/driver.h | 3 +++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 168dd831551d..2c71e8db95a3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -191,6 +191,28 @@ static int gpiochip_find_base(int ngpio) } } +static int gpiochip_init_valid_mask(struct gpio_chip *chip) +{ + if (!chip->need_valid_mask) + return 0; + + chip->valid_mask = kmalloc_array(BITS_TO_LONGS(chip->ngpio), + sizeof(long), GFP_KERNEL); + if (!chip->valid_mask) + return -ENOMEM; + + /* Assume by default all GPIOs are valid */ + bitmap_fill(chip->valid_mask, chip->ngpio); + + return 0; +} + +static void gpiochip_remove_valid_mask(struct gpio_chip *chip) +{ + kfree(chip->valid_mask); + chip->valid_mask = NULL; +} + /** * gpiod_get_direction - return the current direction of a GPIO * @desc: GPIO to get the direction of @@ -1225,10 +1247,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, if (status) goto err_remove_from_list; - status = gpiochip_irqchip_init_valid_mask(chip); + status = gpiochip_init_valid_mask(chip); if (status) goto err_remove_from_list; + status = gpiochip_irqchip_init_valid_mask(chip); + if (status) + goto err_remove_valid_mask; + status = gpiochip_add_irqchip(chip, key); if (status) goto err_remove_chip; @@ -1259,6 +1285,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, gpiochip_free_hogs(chip); of_gpiochip_remove(chip); gpiochip_irqchip_free_valid_mask(chip); +err_remove_valid_mask: + gpiochip_remove_valid_mask(chip); err_remove_from_list: spin_lock_irqsave(&gpio_lock, flags); list_del(&gdev->list); @@ -1311,6 +1339,7 @@ void gpiochip_remove(struct gpio_chip *chip) /* Numb the device, cancelling all outstanding operations */ gdev->chip = NULL; gpiochip_irqchip_remove(chip); + gpiochip_remove_valid_mask(chip); acpi_gpiochip_remove(chip); gpiochip_remove_pin_ranges(chip); of_gpiochip_remove(chip); @@ -1500,6 +1529,18 @@ static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, return test_bit(offset, gpiochip->irq.valid_mask); } +static bool gpiochip_available(const struct gpio_chip *gpiochip, + unsigned int offset) +{ + pr_info("%s:%u offset=%u\n", __func__, __LINE__, offset); + + /* No mask means all valid */ + if (likely(!gpiochip->valid_mask)) + return true; + + return test_bit(offset, gpiochip->valid_mask); +} + /** * gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip * @gpiochip: the gpiochip to set the irqchip chain to @@ -3597,6 +3638,10 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, return desc; } + /* Check if the GPIO line itself is valid */ + if (!gpiochip_available(desc->gdev->chip, idx)) + return ERR_PTR(-EACCES); + status = gpiod_request(desc, con_id); if (status < 0) return ERR_PTR(status); diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 55e672592fa9..b68450caf554 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -316,6 +316,9 @@ struct gpio_chip { int (*of_xlate)(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags); #endif + + bool need_valid_mask; + unsigned long *valid_mask; }; extern const char *gpiochip_is_requested(struct gpio_chip *chip,