From patchwork Mon May 13 15:36:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fabrizio Castro X-Patchwork-Id: 10941263 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5D43F933 for ; Mon, 13 May 2019 15:39:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 46CB4283A6 for ; Mon, 13 May 2019 15:39:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 39A72283AF; Mon, 13 May 2019 15:39:09 +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=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B32A6283A6 for ; Mon, 13 May 2019 15:39:08 +0000 (UTC) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C13F5ED0; Mon, 13 May 2019 15:37:54 +0000 (UTC) X-Original-To: cip-dev@lists.cip-project.org Delivered-To: cip-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 1111BEB7 for ; Mon, 13 May 2019 15:37:54 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp1.linuxfoundation.org (Postfix) with ESMTP id 2C2F927B for ; Mon, 13 May 2019 15:37:53 +0000 (UTC) X-IronPort-AV: E=Sophos;i="5.60,465,1549897200"; d="scan'208";a="15810578" Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 14 May 2019 00:37:52 +0900 Received: from fabrizio-dev.ree.adwin.renesas.com (unknown [10.226.36.196]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id A6A76401BBEF; Tue, 14 May 2019 00:37:51 +0900 (JST) From: Fabrizio Castro To: cip-dev@lists.cip-project.org Date: Mon, 13 May 2019 16:36:44 +0100 Message-Id: <1557761837-24993-20-git-send-email-fabrizio.castro@bp.renesas.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1557761837-24993-1-git-send-email-fabrizio.castro@bp.renesas.com> References: <1557761837-24993-1-git-send-email-fabrizio.castro@bp.renesas.com> Cc: Biju Das Subject: [cip-dev] [PATCH 4.4.y 19/52] gpiolib: Support 'gpio-reserved-ranges' property X-BeenThere: cip-dev@lists.cip-project.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: cip-dev-bounces@lists.cip-project.org Errors-To: cip-dev-bounces@lists.cip-project.org X-Virus-Scanned: ClamAV using ClamSMTP From: Stephen Boyd commit 726cb3ba49692bdae6caff457755e7cdb432efa4 upstream. Some qcom platforms make some GPIOs or pins unavailable for use by non-secure operating systems, and thus reading or writing the registers for those pins will cause access control issues. Add support for a DT property to describe the set of GPIOs that are available for use so that higher level OSes are able to know what pins to avoid reading/writing. Non-DT platforms can add support by directly updating the chip->valid_mask. Signed-off-by: Stephen Boyd Signed-off-by: Stephen Boyd Tested-by: Timur Tabi Reviewed-by: Andy Shevchenko Signed-off-by: Linus Walleij [fab: replaced chip->of_node with chip->dev->of_node, and removed err_remove_irqchip_mask] Signed-off-by: Fabrizio Castro --- drivers/gpio/gpiolib-of.c | 24 ++++++++++++++++++++++++ drivers/gpio/gpiolib.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/gpio/driver.h | 18 ++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 5fe34a9d..ec642bf 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -334,6 +334,28 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) } EXPORT_SYMBOL(of_mm_gpiochip_remove); +static void of_gpiochip_init_valid_mask(struct gpio_chip *chip) +{ + int len, i; + u32 start, count; + struct device_node *np = chip->dev->of_node; + + len = of_property_count_u32_elems(np, "gpio-reserved-ranges"); + if (len < 0 || len % 2 != 0) + return; + + for (i = 0; i < len; i += 2) { + of_property_read_u32_index(np, "gpio-reserved-ranges", + i, &start); + of_property_read_u32_index(np, "gpio-reserved-ranges", + i + 1, &count); + if (start >= chip->ngpio || start + count >= chip->ngpio) + continue; + + bitmap_clear(chip->valid_mask, start, count); + } +}; + #ifdef CONFIG_PINCTRL static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { @@ -434,6 +456,8 @@ int of_gpiochip_add(struct gpio_chip *chip) chip->of_xlate = of_gpio_simple_xlate; } + of_gpiochip_init_valid_mask(chip); + status = of_gpiochip_add_pin_range(chip); if (status) return status; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 0e4e753..d2b0386 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -293,6 +293,43 @@ static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) return p; } +static int gpiochip_init_valid_mask(struct gpio_chip *gpiochip) +{ +#ifdef CONFIG_OF_GPIO + int size; + struct device_node *np = gpiochip->dev->of_node; + + size = of_property_count_u32_elems(np, "gpio-reserved-ranges"); + if (size > 0 && size % 2 == 0) + gpiochip->need_valid_mask = true; +#endif + + if (!gpiochip->need_valid_mask) + return 0; + + gpiochip->valid_mask = gpiochip_allocate_mask(gpiochip); + if (!gpiochip->valid_mask) + return -ENOMEM; + + return 0; +} + +static void gpiochip_free_valid_mask(struct gpio_chip *gpiochip) +{ + kfree(gpiochip->valid_mask); + gpiochip->valid_mask = NULL; +} + +bool gpiochip_line_is_valid(const struct gpio_chip *gpiochip, + unsigned int offset) +{ + /* No mask means all valid */ + if (likely(!gpiochip->valid_mask)) + return true; + return test_bit(offset, gpiochip->valid_mask); +} +EXPORT_SYMBOL_GPL(gpiochip_line_is_valid); + /** * gpiochip_add_data() - register a gpio_chip * @chip: the chip to register, with chip->base initialized @@ -371,6 +408,10 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) if (status) goto err_remove_from_list; + status = gpiochip_init_valid_mask(chip); + if (status) + goto err_remove_from_list; + status = of_gpiochip_add(chip); if (status) goto err_remove_chip; @@ -391,6 +432,7 @@ err_remove_chip: acpi_gpiochip_remove(chip); gpiochip_free_hogs(chip); of_gpiochip_remove(chip); + gpiochip_free_valid_mask(chip); err_remove_from_list: spin_lock_irqsave(&gpio_lock, flags); list_del(&chip->list); @@ -428,6 +470,7 @@ void gpiochip_remove(struct gpio_chip *chip) gpiochip_remove_pin_ranges(chip); gpiochip_free_hogs(chip); of_gpiochip_remove(chip); + gpiochip_free_valid_mask(chip); spin_lock_irqsave(&gpio_lock, flags); for (id = 0; id < chip->ngpio; id++) { diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index de502c7..c0fc8ef 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -143,6 +143,21 @@ struct gpio_chip { struct lock_class_key *lock_key; #endif + /** + * @need_valid_mask: + * + * If set core allocates @valid_mask with all bits set to one. + */ + bool need_valid_mask; + + /** + * @valid_mask: + * + * If not %NULL holds bitmask of GPIOs which are valid to be used + * from the chip. + */ + unsigned long *valid_mask; + #if defined(CONFIG_OF_GPIO) /* * If CONFIG_OF is enabled, then all GPIO controllers described in the @@ -185,6 +200,9 @@ extern struct gpio_chip *gpiochip_find(void *data, int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); +/* */ +bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset); + /* get driver data */ static inline void *gpiochip_get_data(struct gpio_chip *chip) {