From: Stephen Boyd <sboyd@codeaurora.org> To: Linus Walleij <linus.walleij@linaro.org> Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Timur Tabi <timur@codeaurora.org>, Andy Shevchenko <andriy.shevchenko@linux.intel.com>, Bjorn Andersson <bjorn.andersson@linaro.org>, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH 3/3] pinctrl: qcom: Don't allow protected pins to be requested Date: Tue, 9 Jan 2018 17:58:48 -0800 [thread overview] Message-ID: <20180110015848.11480-4-sboyd@codeaurora.org> (raw) In-Reply-To: <20180110015848.11480-1-sboyd@codeaurora.org> 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 <sboyd@codeaurora.org> --- drivers/pinctrl/qcom/pinctrl-msm.c | 98 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 7a960590ecaa..4a251268ebc4 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_irqchip_irq_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_irqchip_irq_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,76 @@ static void msm_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static int msm_gpio_init_irq_valid_mask(struct gpio_chip *chip, + struct msm_pinctrl *pctrl) +{ + int ret; + unsigned int len, i; + unsigned int max_gpios = pctrl->soc->ngpios; + struct device_node *np = pctrl->dev->of_node; + + /* 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->irq_valid_mask, max_gpios); + for (i = 0; i < len; i++) + set_bit(tmp[i], chip->irq_valid_mask); + + return 0; + } + + /* If there's a DT ngpios-ranges property then add those ranges */ + ret = of_property_count_u32_elems(np, "ngpios-ranges"); + if (ret > 0 && ret % 2 == 0 && ret / 2 < max_gpios) { + u32 start; + u32 count; + + len = ret / 2; + bitmap_zero(chip->irq_valid_mask, max_gpios); + + for (i = 0; i < len; i++) { + of_property_read_u32_index(np, "ngpios-ranges", + i * 2, &start); + of_property_read_u32_index(np, "ngpios-ranges", + i * 2 + 1, &count); + bitmap_set(chip->irq_valid_mask, start, count); + } + } + + return 0; +} + +static bool msm_gpio_needs_irq_valid_mask(struct msm_pinctrl *pctrl) +{ + int ret; + struct device_node *np = pctrl->dev->of_node; + + ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0); + if (ret > 0) + return true; + + ret = of_property_count_u32_elems(np, "ngpios-ranges"); + if (ret > 0 && ret % 2 == 0) + return true; + + return false; +} + static int msm_gpio_init(struct msm_pinctrl *pctrl) { struct gpio_chip *chip; @@ -824,6 +907,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->irq_need_valid_mask = msm_gpio_needs_irq_valid_mask(pctrl); ret = gpiochip_add_data(&pctrl->chip, pctrl); if (ret) { @@ -831,6 +915,12 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) return ret; } + ret = msm_gpio_init_irq_valid_mask(chip, pctrl); + if (ret) { + dev_err(pctrl->dev, "Failed to setup irq valid bits\n"); + 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"); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
WARNING: multiple messages have this Message-ID (diff)
From: sboyd@codeaurora.org (Stephen Boyd) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 3/3] pinctrl: qcom: Don't allow protected pins to be requested Date: Tue, 9 Jan 2018 17:58:48 -0800 [thread overview] Message-ID: <20180110015848.11480-4-sboyd@codeaurora.org> (raw) In-Reply-To: <20180110015848.11480-1-sboyd@codeaurora.org> 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 <sboyd@codeaurora.org> --- drivers/pinctrl/qcom/pinctrl-msm.c | 98 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 7a960590ecaa..4a251268ebc4 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_irqchip_irq_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_irqchip_irq_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,76 @@ static void msm_gpio_irq_handler(struct irq_desc *desc) chained_irq_exit(chip, desc); } +static int msm_gpio_init_irq_valid_mask(struct gpio_chip *chip, + struct msm_pinctrl *pctrl) +{ + int ret; + unsigned int len, i; + unsigned int max_gpios = pctrl->soc->ngpios; + struct device_node *np = pctrl->dev->of_node; + + /* 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->irq_valid_mask, max_gpios); + for (i = 0; i < len; i++) + set_bit(tmp[i], chip->irq_valid_mask); + + return 0; + } + + /* If there's a DT ngpios-ranges property then add those ranges */ + ret = of_property_count_u32_elems(np, "ngpios-ranges"); + if (ret > 0 && ret % 2 == 0 && ret / 2 < max_gpios) { + u32 start; + u32 count; + + len = ret / 2; + bitmap_zero(chip->irq_valid_mask, max_gpios); + + for (i = 0; i < len; i++) { + of_property_read_u32_index(np, "ngpios-ranges", + i * 2, &start); + of_property_read_u32_index(np, "ngpios-ranges", + i * 2 + 1, &count); + bitmap_set(chip->irq_valid_mask, start, count); + } + } + + return 0; +} + +static bool msm_gpio_needs_irq_valid_mask(struct msm_pinctrl *pctrl) +{ + int ret; + struct device_node *np = pctrl->dev->of_node; + + ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0); + if (ret > 0) + return true; + + ret = of_property_count_u32_elems(np, "ngpios-ranges"); + if (ret > 0 && ret % 2 == 0) + return true; + + return false; +} + static int msm_gpio_init(struct msm_pinctrl *pctrl) { struct gpio_chip *chip; @@ -824,6 +907,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->irq_need_valid_mask = msm_gpio_needs_irq_valid_mask(pctrl); ret = gpiochip_add_data(&pctrl->chip, pctrl); if (ret) { @@ -831,6 +915,12 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl) return ret; } + ret = msm_gpio_init_irq_valid_mask(chip, pctrl); + if (ret) { + dev_err(pctrl->dev, "Failed to setup irq valid bits\n"); + 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"); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
next prev parent reply other threads:[~2018-01-10 1:58 UTC|newest] Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-01-10 1:58 [PATCH 0/3] Support qcom pinctrl protected pins Stephen Boyd 2018-01-10 1:58 ` Stephen Boyd [not found] ` <20180110015848.11480-1-sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> 2018-01-10 1:58 ` [PATCH 1/3] gpiolib: Export gpiochip_irqchip_irq_valid() to drivers Stephen Boyd 2018-01-10 1:58 ` Stephen Boyd 2018-01-10 1:58 ` Stephen Boyd 2018-01-10 6:16 ` Bjorn Andersson 2018-01-10 6:16 ` Bjorn Andersson 2018-01-10 13:22 ` Linus Walleij 2018-01-10 13:22 ` Linus Walleij 2018-01-10 13:22 ` Linus Walleij 2018-01-10 1:58 ` [PATCH 2/3] dt-bindings: pinctrl: Add a ngpios-ranges property Stephen Boyd 2018-01-10 1:58 ` Stephen Boyd 2018-01-10 12:54 ` Andy Shevchenko 2018-01-10 12:54 ` Andy Shevchenko [not found] ` <20180110015848.11480-3-sboyd-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org> 2018-01-10 13:37 ` Linus Walleij 2018-01-10 13:37 ` Linus Walleij 2018-01-10 13:37 ` Linus Walleij 2018-01-10 16:37 ` Stephen Boyd 2018-01-10 16:37 ` Stephen Boyd 2018-01-10 16:37 ` Stephen Boyd 2018-01-10 17:59 ` Andy Shevchenko 2018-01-10 17:59 ` Andy Shevchenko 2018-01-10 17:59 ` Andy Shevchenko 2018-01-11 16:33 ` Grant Likely 2018-01-11 16:33 ` Grant Likely 2018-01-11 16:33 ` Grant Likely 2018-01-11 16:36 ` Timur Tabi 2018-01-11 16:36 ` Timur Tabi 2018-01-11 16:36 ` Timur Tabi 2018-01-11 19:56 ` Grant Likely 2018-01-11 19:56 ` Grant Likely 2018-01-11 19:56 ` Grant Likely 2018-01-10 1:58 ` Stephen Boyd [this message] 2018-01-10 1:58 ` [PATCH 3/3] pinctrl: qcom: Don't allow protected pins to be requested Stephen Boyd 2018-01-10 6:11 ` Bjorn Andersson 2018-01-10 6:11 ` Bjorn Andersson 2018-01-22 13:55 ` Timur Tabi 2018-01-22 13:55 ` Timur Tabi 2018-01-22 20:03 ` Timur Tabi 2018-01-22 20:03 ` Timur Tabi 2018-01-22 20:03 ` Timur Tabi 2018-01-25 21:51 ` Stephen Boyd 2018-01-25 21:51 ` Stephen Boyd 2018-01-25 21:53 ` Timur Tabi 2018-01-25 21:53 ` Timur Tabi 2018-01-25 20:48 ` Timur Tabi 2018-01-25 20:48 ` Timur Tabi
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20180110015848.11480-4-sboyd@codeaurora.org \ --to=sboyd@codeaurora.org \ --cc=andriy.shevchenko@linux.intel.com \ --cc=bjorn.andersson@linaro.org \ --cc=devicetree@vger.kernel.org \ --cc=linus.walleij@linaro.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-arm-msm@vger.kernel.org \ --cc=linux-gpio@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=timur@codeaurora.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.