From patchwork Wed Mar 21 16:58:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 888944 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="eUZE7trA"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 405wxy1cfwz9s0y for ; Thu, 22 Mar 2018 03:59:18 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752088AbeCUQ6z (ORCPT ); Wed, 21 Mar 2018 12:58:55 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:35717 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751586AbeCUQ6w (ORCPT ); Wed, 21 Mar 2018 12:58:52 -0400 Received: by mail-pf0-f194.google.com with SMTP id y186so2216822pfb.2 for ; Wed, 21 Mar 2018 09:58:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=IsEWvgJNcKsjkd8SgDGPMM8oASotOa0bRX2Uz5aPRz4=; b=eUZE7trArtnpGQ+ass4gltzLJ/Y2c6gKUuqIew50pDpt3ym2qEel822QDk7vVRsD6q SW0LMJ7wnJ+7TUbCN8o/kORcow6QCFrIzv3fSAlw2tX0BpLPVVNfnLuSBHOEURV/Mqhw v5xcLdeh//1xUdmCVyftf9fYcPE+wh6szSIP4= 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:in-reply-to :references; bh=IsEWvgJNcKsjkd8SgDGPMM8oASotOa0bRX2Uz5aPRz4=; b=ViPk8Xra2wrDeRTpyI/Y0vtq29cvIpp7WT91+vBOr/+G7wvFZyODosBtEdXMkc/P2A h+xEE2SzNjD4Si1CdZnfbWrQOaCGR2Ihz0Znu6n73BZoXKMsJfrXuqLfYSIM4xu/xtqI t39OisbdyryaE8y8Y95Q2LT6bJgazQrh0MCdtGdMjaw/68EuN+fI1vW2P/AaKSrWsfJY ytrB5U0hOdJcC/ECZyt7uXYXQvF1HbQ5NWTjrn764Sy+tHQIo9+GN27cB+iB1/LNStA1 kjt2dLMRqkOaKKiNyTILUxw96M6bMwI96+Ydm8Dldk1o1+VSY8HE7mlTPsVdiMWXdCNJ 9DHA== X-Gm-Message-State: AElRT7Epvl9vjnjVROl1OHs2KWY0qLys+WYPs0lssMu3OyysJwe481N2 ZvntqpX0K7NrN3MQMzs9iPPEVQ== X-Google-Smtp-Source: AG47ELtPGd0YthNm11m1F03q7ovnUpUTLpstVC0NBR6S5jRRYr4UnEY2ARJHyFn29bC7fgLOTklYhw== X-Received: by 10.98.37.132 with SMTP id l126mr17746314pfl.102.1521651532265; Wed, 21 Mar 2018 09:58:52 -0700 (PDT) Received: from swboyd.mtv.corp.google.com ([2620:0:1000:1511:d30e:62c6:f82c:ff40]) by smtp.gmail.com with ESMTPSA id u28sm10121806pfl.19.2018.03.21.09.58.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Mar 2018 09:58:51 -0700 (PDT) From: Stephen Boyd To: Linus Walleij Cc: Stephen Boyd , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, Timur Tabi , Bjorn Andersson , Grant Likely , linux-gpio@vger.kernel.org, Andy Shevchenko Subject: [PATCH v3 1/3] dt-bindings: gpio: Add a gpio-reserved-ranges property Date: Wed, 21 Mar 2018 09:58:46 -0700 Message-Id: <20180321165848.89751-2-swboyd@chromium.org> X-Mailer: git-send-email 2.16.2.804.g6dcf76e118-goog In-Reply-To: <20180321165848.89751-1-swboyd@chromium.org> References: <20180321165848.89751-1-swboyd@chromium.org> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Stephen Boyd 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. Introduce 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. Cc: Grant Likely Cc: Signed-off-by: Stephen Boyd Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/gpio/gpio.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt index b5de08e3b1a2..a7c31de29362 100644 --- a/Documentation/devicetree/bindings/gpio/gpio.txt +++ b/Documentation/devicetree/bindings/gpio/gpio.txt @@ -151,9 +151,9 @@ in a lot of designs, some using all 32 bits, some using 18 and some using first 18 GPIOs, at local offset 0 .. 17, are in use. If these GPIOs do not happen to be the first N GPIOs at offset 0...N-1, an -additional bitmask is needed to specify which GPIOs are actually in use, -and which are dummies. The bindings for this case has not yet been -specified, but should be specified if/when such hardware appears. +additional set of tuples is needed to specify which GPIOs are unusable, with +the gpio-reserved-ranges binding. This property indicates the start and size +of the GPIOs that can't be used. Optionally, a GPIO controller may have a "gpio-line-names" property. This is an array of strings defining the names of the GPIO lines going out of the @@ -178,6 +178,7 @@ gpio-controller@00000000 { gpio-controller; #gpio-cells = <2>; ngpios = <18>; + gpio-reserved-ranges = <0 4>, <12 2>; gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R", "LED G", "LED B", "Col A", "Col B", "Col C", "Col D", "Row A", "Row B", "Row C", "Row D", "NMI button", From patchwork Wed Mar 21 16:58:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 888947 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="CPB8xJ4B"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 405wyX3YkTz9s0n for ; Thu, 22 Mar 2018 03:59:48 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752317AbeCUQ7q (ORCPT ); Wed, 21 Mar 2018 12:59:46 -0400 Received: from mail-pg0-f65.google.com ([74.125.83.65]:35380 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751980AbeCUQ6x (ORCPT ); Wed, 21 Mar 2018 12:58:53 -0400 Received: by mail-pg0-f65.google.com with SMTP id d1so2164882pgv.2 for ; Wed, 21 Mar 2018 09:58:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=I5kzN9Lak1dkyQmXG7fgEFlSGMI1oR7RK56a3QuzoXg=; b=CPB8xJ4Bw9fSX1PjGORwJ+bNaT864WFDMK5+g7n885O5Rwsh/3ACNObG36ay9P61ox l39H70q2MwxtRPA1NO3KbzQlQ0bUWWCIX/i/uCdZOmSttZ69QgPgsQj6AGQ40cyPDXyc nwhSMCuwdXErZCAZNnvcozWKPJcEPFxTXE5EQ= 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:in-reply-to :references; bh=I5kzN9Lak1dkyQmXG7fgEFlSGMI1oR7RK56a3QuzoXg=; b=GAvMSlYU1xBebHHuVOGHn8eoN/br4d2jWB97jkd+TJRYjniCKP300NSiQllwYTgQnr qDLKhL36butkaQNSLJOMZYWYEBOhzpapROitcu7ftikwGJ8hCwl1AQGZPP5y+Sajx9Or RDGE6dYwf8xgU0Y1IDberNMgmdp6a9tx7r/a0rl05tpzGtMLfd9457SdReh90dNAi39O EuPjL0SryHfpmjcg5x9nKoc22bMtd7kThsiMGwugom51bN2w0VtKOONf+UDY51s7ZIUj fHJO9MwurjrARhKx8FbYGJ1+aazT614XhprTQKjbF3mNVNVHnDjhqmpkGzDawlIkRTvo Fx4w== X-Gm-Message-State: AElRT7FY3WeHtBj8bTOSVhJvLU+1DJEpGQBK8Nko7AF3aJDIn/PWdmlt S2Uutfb6XBsdEH4DiwmcYsSF+A== X-Google-Smtp-Source: AG47ELu5F6wJygoLAfwake0JqlESWvfOZh+VGCO4U9zbs493yc2ZNZHfqvQods7IctovccctJ/RaEw== X-Received: by 10.98.32.134 with SMTP id m6mr17647270pfj.27.1521651533088; Wed, 21 Mar 2018 09:58:53 -0700 (PDT) Received: from swboyd.mtv.corp.google.com ([2620:0:1000:1511:d30e:62c6:f82c:ff40]) by smtp.gmail.com with ESMTPSA id u28sm10121806pfl.19.2018.03.21.09.58.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Mar 2018 09:58:52 -0700 (PDT) From: Stephen Boyd To: Linus Walleij Cc: Stephen Boyd , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, Timur Tabi , Bjorn Andersson , Grant Likely , linux-gpio@vger.kernel.org, Andy Shevchenko Subject: [PATCH v3 2/3] gpiolib: Support 'gpio-reserved-ranges' property Date: Wed, 21 Mar 2018 09:58:47 -0700 Message-Id: <20180321165848.89751-3-swboyd@chromium.org> X-Mailer: git-send-email 2.16.2.804.g6dcf76e118-goog In-Reply-To: <20180321165848.89751-1-swboyd@chromium.org> References: <20180321165848.89751-1-swboyd@chromium.org> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Stephen Boyd 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 --- drivers/gpio/gpiolib-of.c | 24 ++++++++++++++++++ drivers/gpio/gpiolib.c | 50 +++++++++++++++++++++++++++++++++++++ include/linux/gpio/driver.h | 16 ++++++++++++ 3 files changed, 90 insertions(+) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 84e5a9df2344..ed81d9a6316f 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -511,6 +511,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->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) { @@ -615,6 +637,8 @@ int of_gpiochip_add(struct gpio_chip *chip) if (chip->of_gpio_n_cells > MAX_PHANDLE_ARGS) return -EINVAL; + 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 d66de67ef307..5861984774ac 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -337,6 +337,47 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) return 0; } +static int gpiochip_init_valid_mask(struct gpio_chip *gpiochip) +{ +#ifdef CONFIG_OF_GPIO + int size; + struct device_node *np = gpiochip->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 = kcalloc(BITS_TO_LONGS(gpiochip->ngpio), + sizeof(long), GFP_KERNEL); + if (!gpiochip->valid_mask) + return -ENOMEM; + + /* Assume by default all GPIOs are valid */ + bitmap_fill(gpiochip->valid_mask, gpiochip->ngpio); + + 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); + /* * GPIO line handle management */ @@ -1261,6 +1302,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, if (status) goto err_remove_from_list; + status = gpiochip_init_valid_mask(chip); + if (status) + goto err_remove_irqchip_mask; + status = gpiochip_add_irqchip(chip, lock_key, request_key); if (status) goto err_remove_chip; @@ -1290,6 +1335,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, acpi_gpiochip_remove(chip); gpiochip_free_hogs(chip); of_gpiochip_remove(chip); + gpiochip_free_valid_mask(chip); +err_remove_irqchip_mask: gpiochip_irqchip_free_valid_mask(chip); err_remove_from_list: spin_lock_irqsave(&gpio_lock, flags); @@ -1346,6 +1393,7 @@ void gpiochip_remove(struct gpio_chip *chip) acpi_gpiochip_remove(chip); gpiochip_remove_pin_ranges(chip); of_gpiochip_remove(chip); + gpiochip_free_valid_mask(chip); /* * We accept no more calls into the driver from this point, so * NULL the driver data pointer @@ -1526,6 +1574,8 @@ static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, unsigned int offset) { + if (!gpiochip_line_is_valid(gpiochip, offset)) + return false; /* No mask means all valid */ if (likely(!gpiochip->irq.valid_mask)) return true; diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 1ba9a331ec51..5382b5183b7e 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -288,6 +288,21 @@ struct gpio_chip { struct gpio_irq_chip irq; #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 @@ -384,6 +399,7 @@ bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset); /* Sleep persistence inquiry for drivers */ bool gpiochip_line_is_persistent(struct gpio_chip *chip, unsigned int offset); +bool gpiochip_line_is_valid(const struct gpio_chip *chip, unsigned int offset); /* get driver data */ void *gpiochip_get_data(struct gpio_chip *chip); From patchwork Wed Mar 21 16:58:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 888943 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="ETnaWS8h"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 405wxx1VJfz9s0n for ; Thu, 22 Mar 2018 03:59:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751673AbeCUQ7P (ORCPT ); Wed, 21 Mar 2018 12:59:15 -0400 Received: from mail-pg0-f66.google.com ([74.125.83.66]:42617 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752061AbeCUQ6z (ORCPT ); Wed, 21 Mar 2018 12:58:55 -0400 Received: by mail-pg0-f66.google.com with SMTP id f10so1994494pgs.9 for ; Wed, 21 Mar 2018 09:58:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Pd45ONlBRVfl7OnQvb7vYtWuUyQEYLzIYWuKrG6wNO0=; b=ETnaWS8hcMqLoIO9CZe1SDAZXt7/bb/iD6pCMZC1Bwrq8DTdvgns4Vptf+MHLa/DKy IutUkzoCP32yY2lvkQv8xANiOPshIL5OiKkjY7NCXd+NFwPF43+07YLptFw6yJJOt/Qu 5vrczz9cDxbmYKGqq+vETSSGmov0yN6GAUyNg= 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:in-reply-to :references; bh=Pd45ONlBRVfl7OnQvb7vYtWuUyQEYLzIYWuKrG6wNO0=; b=c489Y4oKd1pc327pr5yWcXb7NXOORd/RvkIFb8Ibv+BYd40oBfpMYGMtOLU051Rvlo kBVhWg6TEdQg3bHV87E3EDkLTrZ3/zh4WrhEnfvTcXzmaMk5MFBzWS4sH8y/2bD9rc6D 3j5/N1f5WtPXWoVT1U5CaBePpISPlWn/yR9yZ5s9cXCNZmyJmrm+neCoQMITfuLsbdVQ BVZ8xcT7HvTwLMmGHFj9faY+zVOibEI1APupLuA2KIzKi5jDN/Pog6ctxuEANjiToIdW TrYKEzaEhL7oEXHZ4QSVeHQjK1OJ5hIW/GiD6FdRAuXQxXEqwqK7YOYkCYXyexGah2ca sINQ== X-Gm-Message-State: AElRT7Gq6HF3iyDWdJ35YHy/r2lJFmBs5xeHKUYkIPNhQVOSNnUtBNkv NJ4aJ7/yrgi3wnhSd5NumBNf4Q== X-Google-Smtp-Source: AG47ELs7hLz4Lg7ZCBQLbMa7YhHj4qu+Nc9gOCl26K7mn/Pw9316i3ORNauNLF5U+caB3MWssRqKQw== X-Received: by 10.98.89.23 with SMTP id n23mr8637976pfb.211.1521651534094; Wed, 21 Mar 2018 09:58:54 -0700 (PDT) Received: from swboyd.mtv.corp.google.com ([2620:0:1000:1511:d30e:62c6:f82c:ff40]) by smtp.gmail.com with ESMTPSA id u28sm10121806pfl.19.2018.03.21.09.58.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Mar 2018 09:58:53 -0700 (PDT) From: Stephen Boyd To: Linus Walleij Cc: Stephen Boyd , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-msm@vger.kernel.org, Timur Tabi , Bjorn Andersson , Grant Likely , linux-gpio@vger.kernel.org, Andy Shevchenko Subject: [PATCH v3 3/3] pinctrl: qcom: Don't allow protected pins to be requested Date: Wed, 21 Mar 2018 09:58:48 -0700 Message-Id: <20180321165848.89751-4-swboyd@chromium.org> X-Mailer: git-send-email 2.16.2.804.g6dcf76e118-goog In-Reply-To: <20180321165848.89751-1-swboyd@chromium.org> References: <20180321165848.89751-1-swboyd@chromium.org> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: Stephen Boyd 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 and reset the device. With a DT/ACPI property to describe the set of pins that are available for use, parse the available pins and set the irq valid bits for gpiolib to know what to consider 'valid'. This should avoid any issues with gpiolib. Furthermore, implement the pinmux_ops::request function so that pinmux can also make sure to not use pins that are unavailable. Signed-off-by: Stephen Boyd Signed-off-by: Stephen Boyd --- drivers/pinctrl/qcom/pinctrl-msm.c | 69 ++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 495432f3341b..bc9cda0da886 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -105,6 +105,17 @@ static const struct pinctrl_ops msm_pinctrl_ops = { .dt_free_map = pinctrl_utils_free_map, }; +static int msm_pinmux_request(struct pinctrl_dev *pctldev, unsigned offset) +{ + struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + struct gpio_chip *chip = &pctrl->chip; + + if (gpiochip_line_is_valid(chip, offset)) + return 0; + + return -EINVAL; +} + static int msm_get_functions_count(struct pinctrl_dev *pctldev) { struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); @@ -166,6 +177,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev, } static const struct pinmux_ops msm_pinmux_ops = { + .request = msm_pinmux_request, .get_functions_count = msm_get_functions_count, .get_function_name = msm_get_function_name, .get_function_groups = msm_get_function_groups, @@ -506,6 +518,9 @@ static void msm_gpio_dbg_show_one(struct seq_file *s, "pull up" }; + if (!gpiochip_line_is_valid(chip, offset)) + return; + g = &pctrl->soc->groups[offset]; ctl_reg = readl(pctrl->regs + g->ctl_reg); @@ -516,7 +531,7 @@ static void msm_gpio_dbg_show_one(struct seq_file *s, seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func); seq_printf(s, " %dmA", msm_regval_to_drive(drive)); - seq_printf(s, " %s", pulls[pull]); + seq_printf(s, " %s\n", pulls[pull]); } static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) @@ -524,10 +539,8 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) unsigned gpio = chip->base; unsigned i; - for (i = 0; i < chip->ngpio; i++, gpio++) { + for (i = 0; i < chip->ngpio; i++, gpio++) msm_gpio_dbg_show_one(s, NULL, chip, i, gpio); - seq_puts(s, "\n"); - } } #else @@ -808,6 +821,46 @@ static void msm_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static int msm_gpio_init_valid_mask(struct gpio_chip *chip, + struct msm_pinctrl *pctrl) +{ + int ret; + unsigned int len, i; + unsigned int max_gpios = pctrl->soc->ngpios; + + /* The number of GPIOs in the ACPI tables */ + ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0); + if (ret > 0 && ret < max_gpios) { + u16 *tmp; + + len = ret; + tmp = kmalloc_array(len, sizeof(tmp[0]), GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + ret = device_property_read_u16_array(pctrl->dev, "gpios", tmp, + len); + if (ret < 0) { + dev_err(pctrl->dev, "could not read list of GPIOs\n"); + kfree(tmp); + return ret; + } + + bitmap_zero(chip->valid_mask, max_gpios); + for (i = 0; i < len; i++) + set_bit(tmp[i], chip->valid_mask); + + return 0; + } + + return 0; +} + +static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl) +{ + return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0; +} + static int msm_gpio_init(struct msm_pinctrl *pctrl) { struct gpio_chip *chip; @@ -824,6 +877,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) chip->parent = pctrl->dev; chip->owner = THIS_MODULE; chip->of_node = pctrl->dev->of_node; + chip->need_valid_mask = msm_gpio_needs_valid_mask(pctrl); ret = gpiochip_add_data(&pctrl->chip, pctrl); if (ret) { @@ -831,6 +885,13 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) return ret; } + ret = msm_gpio_init_valid_mask(chip, pctrl); + if (ret) { + dev_err(pctrl->dev, "Failed to setup irq valid bits\n"); + gpiochip_remove(&pctrl->chip); + return ret; + } + ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio); if (ret) { dev_err(pctrl->dev, "Failed to add pin range\n");