aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2018-03-23 12:34:53 -0400
committerLinus Walleij <linus.walleij@linaro.org>2018-03-27 09:34:25 -0400
commit691bf5d5a7bfedc60b7218f4d9b915bf356df767 (patch)
tree074506c16494fc907fb4e5e9e194e8876ad69f27
parent726cb3ba49692bdae6caff457755e7cdb432efa4 (diff)
pinctrl: qcom: Don't allow protected pins to be requested
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> Signed-off-by: Stephen Boyd <swboyd@chromium.org> Tested-by: Timur Tabi <timur@codeaurora.org> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c65
1 files changed, 62 insertions, 3 deletions
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 495432f3341b..e7abc8ba222b 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -105,6 +105,14 @@ static const struct pinctrl_ops msm_pinctrl_ops = {
105 .dt_free_map = pinctrl_utils_free_map, 105 .dt_free_map = pinctrl_utils_free_map,
106}; 106};
107 107
108static int msm_pinmux_request(struct pinctrl_dev *pctldev, unsigned offset)
109{
110 struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
111 struct gpio_chip *chip = &pctrl->chip;
112
113 return gpiochip_line_is_valid(chip, offset) ? 0 : -EINVAL;
114}
115
108static int msm_get_functions_count(struct pinctrl_dev *pctldev) 116static int msm_get_functions_count(struct pinctrl_dev *pctldev)
109{ 117{
110 struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); 118 struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -166,6 +174,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
166} 174}
167 175
168static const struct pinmux_ops msm_pinmux_ops = { 176static const struct pinmux_ops msm_pinmux_ops = {
177 .request = msm_pinmux_request,
169 .get_functions_count = msm_get_functions_count, 178 .get_functions_count = msm_get_functions_count,
170 .get_function_name = msm_get_function_name, 179 .get_function_name = msm_get_function_name,
171 .get_function_groups = msm_get_function_groups, 180 .get_function_groups = msm_get_function_groups,
@@ -506,6 +515,9 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
506 "pull up" 515 "pull up"
507 }; 516 };
508 517
518 if (!gpiochip_line_is_valid(chip, offset))
519 return;
520
509 g = &pctrl->soc->groups[offset]; 521 g = &pctrl->soc->groups[offset];
510 ctl_reg = readl(pctrl->regs + g->ctl_reg); 522 ctl_reg = readl(pctrl->regs + g->ctl_reg);
511 523
@@ -517,6 +529,7 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
517 seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func); 529 seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func);
518 seq_printf(s, " %dmA", msm_regval_to_drive(drive)); 530 seq_printf(s, " %dmA", msm_regval_to_drive(drive));
519 seq_printf(s, " %s", pulls[pull]); 531 seq_printf(s, " %s", pulls[pull]);
532 seq_puts(s, "\n");
520} 533}
521 534
522static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) 535static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
@@ -524,10 +537,8 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
524 unsigned gpio = chip->base; 537 unsigned gpio = chip->base;
525 unsigned i; 538 unsigned i;
526 539
527 for (i = 0; i < chip->ngpio; i++, gpio++) { 540 for (i = 0; i < chip->ngpio; i++, gpio++)
528 msm_gpio_dbg_show_one(s, NULL, chip, i, gpio); 541 msm_gpio_dbg_show_one(s, NULL, chip, i, gpio);
529 seq_puts(s, "\n");
530 }
531} 542}
532 543
533#else 544#else
@@ -808,6 +819,46 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
808 chained_irq_exit(chip, desc); 819 chained_irq_exit(chip, desc);
809} 820}
810 821
822static int msm_gpio_init_valid_mask(struct gpio_chip *chip,
823 struct msm_pinctrl *pctrl)
824{
825 int ret;
826 unsigned int len, i;
827 unsigned int max_gpios = pctrl->soc->ngpios;
828 u16 *tmp;
829
830 /* The number of GPIOs in the ACPI tables */
831 len = ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0);
832 if (ret < 0)
833 return 0;
834
835 if (ret > max_gpios)
836 return -EINVAL;
837
838 tmp = kmalloc_array(len, sizeof(*tmp), GFP_KERNEL);
839 if (!tmp)
840 return -ENOMEM;
841
842 ret = device_property_read_u16_array(pctrl->dev, "gpios", tmp, len);
843 if (ret < 0) {
844 dev_err(pctrl->dev, "could not read list of GPIOs\n");
845 goto out;
846 }
847
848 bitmap_zero(chip->valid_mask, max_gpios);
849 for (i = 0; i < len; i++)
850 set_bit(tmp[i], chip->valid_mask);
851
852out:
853 kfree(tmp);
854 return ret;
855}
856
857static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl)
858{
859 return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0;
860}
861
811static int msm_gpio_init(struct msm_pinctrl *pctrl) 862static int msm_gpio_init(struct msm_pinctrl *pctrl)
812{ 863{
813 struct gpio_chip *chip; 864 struct gpio_chip *chip;
@@ -824,6 +875,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
824 chip->parent = pctrl->dev; 875 chip->parent = pctrl->dev;
825 chip->owner = THIS_MODULE; 876 chip->owner = THIS_MODULE;
826 chip->of_node = pctrl->dev->of_node; 877 chip->of_node = pctrl->dev->of_node;
878 chip->need_valid_mask = msm_gpio_needs_valid_mask(pctrl);
827 879
828 ret = gpiochip_add_data(&pctrl->chip, pctrl); 880 ret = gpiochip_add_data(&pctrl->chip, pctrl);
829 if (ret) { 881 if (ret) {
@@ -831,6 +883,13 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
831 return ret; 883 return ret;
832 } 884 }
833 885
886 ret = msm_gpio_init_valid_mask(chip, pctrl);
887 if (ret) {
888 dev_err(pctrl->dev, "Failed to setup irq valid bits\n");
889 gpiochip_remove(&pctrl->chip);
890 return ret;
891 }
892
834 ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio); 893 ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio);
835 if (ret) { 894 if (ret) {
836 dev_err(pctrl->dev, "Failed to add pin range\n"); 895 dev_err(pctrl->dev, "Failed to add pin range\n");