From patchwork Mon Sep 13 22:49:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Heiko_St=C3=BCbner?= X-Patchwork-Id: 509991 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D6096C433FE for ; Mon, 13 Sep 2021 22:52:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BC6DB60EFF for ; Mon, 13 Sep 2021 22:52:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350122AbhIMWxk (ORCPT ); Mon, 13 Sep 2021 18:53:40 -0400 Received: from gloria.sntech.de ([185.11.138.130]:51186 "EHLO gloria.sntech.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349679AbhIMWvB (ORCPT ); Mon, 13 Sep 2021 18:51:01 -0400 Received: from ip5f5a6e92.dynamic.kabel-deutschland.de ([95.90.110.146] helo=localhost.localdomain) by gloria.sntech.de with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mPulW-0003SX-C6; Tue, 14 Sep 2021 00:49:30 +0200 From: Heiko Stuebner To: linus.walleij@linaro.org, bgolaszewski@baylibre.com Cc: heiko@sntech.de, jay.xu@rock-chips.com, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/4] gpio/rockchip: fix get_direction value handling Date: Tue, 14 Sep 2021 00:49:24 +0200 Message-Id: <20210913224926.1260726-3-heiko@sntech.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210913224926.1260726-1-heiko@sntech.de> References: <20210913224926.1260726-1-heiko@sntech.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The function uses the newly introduced rockchip_gpio_readl_bit() which directly returns the actual value of the requeste bit. So using the existing bit-wise check for the bit inside the value will always return 0. Fix this by dropping the bit manipulation on the result. Fixes: 3bcbd1a85b68 ("gpio/rockchip: support next version gpio controller") Signed-off-by: Heiko Stuebner Reviewed-by: Linus Walleij --- drivers/gpio/gpio-rockchip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index 16d9bf7188e3..3335bd57761d 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -141,7 +141,7 @@ static int rockchip_gpio_get_direction(struct gpio_chip *chip, u32 data; data = rockchip_gpio_readl_bit(bank, offset, bank->gpio_regs->port_ddr); - if (data & BIT(offset)) + if (data) return GPIO_LINE_DIRECTION_OUT; return GPIO_LINE_DIRECTION_IN; From patchwork Mon Sep 13 22:49:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Heiko_St=C3=BCbner?= X-Patchwork-Id: 509990 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2ADEFC433EF for ; Mon, 13 Sep 2021 22:53:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 122B560F51 for ; Mon, 13 Sep 2021 22:53:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1349923AbhIMWx3 (ORCPT ); Mon, 13 Sep 2021 18:53:29 -0400 Received: from gloria.sntech.de ([185.11.138.130]:51182 "EHLO gloria.sntech.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349677AbhIMWvB (ORCPT ); Mon, 13 Sep 2021 18:51:01 -0400 Received: from ip5f5a6e92.dynamic.kabel-deutschland.de ([95.90.110.146] helo=localhost.localdomain) by gloria.sntech.de with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mPulW-0003SX-LR; Tue, 14 Sep 2021 00:49:30 +0200 From: Heiko Stuebner To: linus.walleij@linaro.org, bgolaszewski@baylibre.com Cc: heiko@sntech.de, jay.xu@rock-chips.com, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/4] pinctrl/rockchip: add a queue for deferred pin output settings on probe Date: Tue, 14 Sep 2021 00:49:25 +0200 Message-Id: <20210913224926.1260726-4-heiko@sntech.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210913224926.1260726-1-heiko@sntech.de> References: <20210913224926.1260726-1-heiko@sntech.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The separation of pinctrl and gpio drivers created a tiny window where a pinconfig setting might produce a null-pointer dereference. The affected device were rk3288-veyron devices in this case. Pinctrl-hogs are claimed when the pinctrl driver is registered, at which point their pinconfig settings will be applied. At this time the now separate gpio devices will not have been created yet and the matching driver won't have probed yet, making the gpio->foo() call run into a null-ptr. As probing is not really guaranteed to have been completed at a specific time, introduce a queue that can hold the output settings until the gpio driver has probed and will (in a separate patch) fetch the elements of the list. We expect the gpio driver to empty the list, but will nevertheless empty it ourself on remove if that didn't happen. Fixes: 9ce9a02039de ("pinctrl/rockchip: drop the gpio related codes") Signed-off-by: Heiko Stuebner --- drivers/pinctrl/pinctrl-rockchip.c | 67 ++++++++++++++++++++++++++++++ drivers/pinctrl/pinctrl-rockchip.h | 10 +++++ 2 files changed, 77 insertions(+) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index ae33e376695f..5ce260f152ce 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -2092,6 +2092,23 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, return false; } +static int rockchip_pinconf_defer_output(struct rockchip_pin_bank *bank, + unsigned int pin, u32 arg) +{ + struct rockchip_pin_output_deferred *cfg; + + cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return -ENOMEM; + + cfg->pin = pin; + cfg->arg = arg; + + list_add_tail(&cfg->head, &bank->deferred_output); + + return 0; +} + /* set the pin config settings for a specified pin */ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *configs, unsigned num_configs) @@ -2136,6 +2153,22 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, if (rc != RK_FUNC_GPIO) return -EINVAL; + /* + * Check for gpio driver not being probed yet. + * The lock makes sure that either gpio-probe has completed + * or the gpio driver hasn't probed yet. + */ + mutex_lock(&bank->deferred_lock); + if (!gpio || !gpio->direction_output) { + rc = rockchip_pinconf_defer_output(bank, pin - bank->pin_base, arg); + mutex_unlock(&bank->deferred_lock); + if (rc) + return rc; + + break; + } + mutex_unlock(&bank->deferred_lock); + rc = gpio->direction_output(gpio, pin - bank->pin_base, arg); if (rc) @@ -2204,6 +2237,11 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, if (rc != RK_FUNC_GPIO) return -EINVAL; + if (!gpio || !gpio->get) { + arg = 0; + break; + } + rc = gpio->get(gpio, pin - bank->pin_base); if (rc < 0) return rc; @@ -2450,6 +2488,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev, pin_bank->name, pin); pdesc++; } + + INIT_LIST_HEAD(&pin_bank->deferred_output); + mutex_init(&pin_bank->deferred_lock); } ret = rockchip_pinctrl_parse_dt(pdev, info); @@ -2716,6 +2757,31 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) return 0; } +static int rockchip_pinctrl_remove(struct platform_device *pdev) +{ + struct rockchip_pinctrl *info = platform_get_drvdata(pdev); + struct rockchip_pin_bank *bank; + struct rockchip_pin_output_deferred *cfg; + int i; + + of_platform_depopulate(&pdev->dev); + + for (i = 0; i < info->ctrl->nr_banks; i++) { + bank = &info->ctrl->pin_banks[i]; + + mutex_lock(&bank->deferred_lock); + while (!list_empty(&bank->deferred_output)) { + cfg = list_first_entry(&bank->deferred_output, + struct rockchip_pin_output_deferred, head); + list_del(&cfg->head); + kfree(cfg); + } + mutex_unlock(&bank->deferred_lock); + } + + return 0; +} + static struct rockchip_pin_bank px30_pin_banks[] = { PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU, IOMUX_SOURCE_PMU, @@ -3175,6 +3241,7 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = { static struct platform_driver rockchip_pinctrl_driver = { .probe = rockchip_pinctrl_probe, + .remove = rockchip_pinctrl_remove, .driver = { .name = "rockchip-pinctrl", .pm = &rockchip_pinctrl_dev_pm_ops, diff --git a/drivers/pinctrl/pinctrl-rockchip.h b/drivers/pinctrl/pinctrl-rockchip.h index 589d4d2a98c9..91f10279d084 100644 --- a/drivers/pinctrl/pinctrl-rockchip.h +++ b/drivers/pinctrl/pinctrl-rockchip.h @@ -141,6 +141,8 @@ struct rockchip_drv { * @toggle_edge_mode: bit mask to toggle (falling/rising) edge mode * @recalced_mask: bit mask to indicate a need to recalulate the mask * @route_mask: bits describing the routing pins of per bank + * @deferred_output: gpio output settings to be done after gpio bank probed + * @deferred_lock: mutex for the deferred_output shared btw gpio and pinctrl */ struct rockchip_pin_bank { struct device *dev; @@ -169,6 +171,8 @@ struct rockchip_pin_bank { u32 toggle_edge_mode; u32 recalced_mask; u32 route_mask; + struct list_head deferred_output; + struct mutex deferred_lock; }; /** @@ -243,6 +247,12 @@ struct rockchip_pin_config { unsigned int nconfigs; }; +struct rockchip_pin_output_deferred { + struct list_head head; + unsigned int pin; + u32 arg; +}; + /** * struct rockchip_pin_group: represent group of pins of a pinmux function. * @name: name of the pin group, used to lookup the group. From patchwork Mon Sep 13 22:49:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Heiko_St=C3=BCbner?= X-Patchwork-Id: 509992 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A7240C433EF for ; Mon, 13 Sep 2021 22:52:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8CFF060EFF for ; Mon, 13 Sep 2021 22:52:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1350014AbhIMWxe (ORCPT ); Mon, 13 Sep 2021 18:53:34 -0400 Received: from gloria.sntech.de ([185.11.138.130]:51178 "EHLO gloria.sntech.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349681AbhIMWvB (ORCPT ); Mon, 13 Sep 2021 18:51:01 -0400 Received: from ip5f5a6e92.dynamic.kabel-deutschland.de ([95.90.110.146] helo=localhost.localdomain) by gloria.sntech.de with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mPulW-0003SX-Uz; Tue, 14 Sep 2021 00:49:31 +0200 From: Heiko Stuebner To: linus.walleij@linaro.org, bgolaszewski@baylibre.com Cc: heiko@sntech.de, jay.xu@rock-chips.com, linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/4] gpio/rockchip: fetch deferred output settings on probe Date: Tue, 14 Sep 2021 00:49:26 +0200 Message-Id: <20210913224926.1260726-5-heiko@sntech.de> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210913224926.1260726-1-heiko@sntech.de> References: <20210913224926.1260726-1-heiko@sntech.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Fetch the output settings the pinctrl driver may have created for pinctrl hogs and set the relevant pins as requested. Fixes: 9ce9a02039de ("pinctrl/rockchip: drop the gpio related codes") Signed-off-by: Heiko Stuebner --- drivers/gpio/gpio-rockchip.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index 3335bd57761d..cf1b465db8c3 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -689,6 +689,7 @@ static int rockchip_gpio_probe(struct platform_device *pdev) struct device_node *pctlnp = of_get_parent(np); struct pinctrl_dev *pctldev = NULL; struct rockchip_pin_bank *bank = NULL; + struct rockchip_pin_output_deferred *cfg; static int gpio; int id, ret; @@ -716,12 +717,33 @@ static int rockchip_gpio_probe(struct platform_device *pdev) if (ret) return ret; + /* + * Prevent clashes with a deferred output setting + * being added right at this moment. + */ + mutex_lock(&bank->deferred_lock); + ret = rockchip_gpiolib_register(bank); if (ret) { clk_disable_unprepare(bank->clk); + mutex_unlock(&bank->deferred_lock); return ret; } + while (!list_empty(&bank->deferred_output)) { + cfg = list_first_entry(&bank->deferred_output, + struct rockchip_pin_output_deferred, head); + list_del(&cfg->head); + + ret = rockchip_gpio_direction_output(&bank->gpio_chip, cfg->pin, cfg->arg); + if (ret) + dev_warn(dev, "setting output pin %u to %u failed\n", cfg->pin, cfg->arg); + + kfree(cfg); + } + + mutex_unlock(&bank->deferred_lock); + platform_set_drvdata(pdev, bank); dev_info(dev, "probed %pOF\n", np);