diff options
author | Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> | 2018-10-05 08:52:59 +0200 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2018-10-10 10:31:57 +0200 |
commit | 6f0ec09afe278ea2a5d63f31b754db6655c69078 (patch) | |
tree | 7c7e101fcff9303678b46df7f86cc3aac34cf4b4 | |
parent | gpiolib: Add init_valid_mask exported function (diff) | |
download | linux-6f0ec09afe278ea2a5d63f31b754db6655c69078.tar.xz linux-6f0ec09afe278ea2a5d63f31b754db6655c69078.zip |
pinctrl: msm: Use init_valid_mask exported function
The current code produces XPU violation if get_direction is called just
after the initialization.
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Acked-by: Timur Tabi <timur@kernel.org>
Tested-by: Jeffrey Hugo <jhugo@codeaurora.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | drivers/pinctrl/qcom/pinctrl-msm.c | 79 |
1 files changed, 37 insertions, 42 deletions
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 2155a30c282b..8366b41ea609 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -566,6 +566,42 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) #define msm_gpio_dbg_show NULL #endif +static int msm_gpio_init_valid_mask(struct gpio_chip *chip) +{ + struct msm_pinctrl *pctrl = gpiochip_get_data(chip); + int ret; + unsigned int len, i; + unsigned int max_gpios = pctrl->soc->ngpios; + u16 *tmp; + + /* The number of GPIOs in the ACPI tables */ + len = ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, + 0); + if (ret < 0) + return 0; + + if (ret > max_gpios) + return -EINVAL; + + tmp = kmalloc_array(len, sizeof(*tmp), 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"); + goto out; + } + + bitmap_zero(chip->valid_mask, max_gpios); + for (i = 0; i < len; i++) + set_bit(tmp[i], chip->valid_mask); + +out: + kfree(tmp); + return ret; +} + static const struct gpio_chip msm_gpio_template = { .direction_input = msm_gpio_direction_input, .direction_output = msm_gpio_direction_output, @@ -575,6 +611,7 @@ static const struct gpio_chip msm_gpio_template = { .request = gpiochip_generic_request, .free = gpiochip_generic_free, .dbg_show = msm_gpio_dbg_show, + .init_valid_mask = msm_gpio_init_valid_mask, }; /* For dual-edge interrupts in software, since some hardware has no @@ -831,41 +868,6 @@ 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; - u16 *tmp; - - /* The number of GPIOs in the ACPI tables */ - len = ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0); - if (ret < 0) - return 0; - - if (ret > max_gpios) - return -EINVAL; - - tmp = kmalloc_array(len, sizeof(*tmp), 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"); - goto out; - } - - bitmap_zero(chip->valid_mask, max_gpios); - for (i = 0; i < len; i++) - set_bit(tmp[i], chip->valid_mask); - -out: - kfree(tmp); - return ret; -} - static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl) { return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0; @@ -902,13 +904,6 @@ 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; - } - /* * For DeviceTree-supported systems, the gpio core checks the * pinctrl's device node for the "gpio-ranges" property. |