diff options
Diffstat (limited to 'drivers/pinctrl/devicetree.c')
-rw-r--r-- | drivers/pinctrl/devicetree.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index dbaacde1b36a..23bfa27788f5 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -7,6 +7,7 @@ #include <linux/device.h> #include <linux/of.h> +#include <linux/of_gpio.h> #include <linux/pinctrl/pinctrl.h> #include <linux/slab.h> @@ -196,6 +197,46 @@ bool pinctrl_dt_has_hogs(struct pinctrl_dev *pctldev) return prop ? true : false; } +static int dt_gpio_assert_pinctrl(struct pinctrl *p) +{ + struct device_node *np = p->dev->of_node; + enum of_gpio_flags flags; + int gpio; + int index = 0; + int ret; + + if (!of_find_property(np, "pinctrl-assert-gpios", NULL)) + return 0; /* Missing the property, so nothing to be done */ + + for (;; index++) { + gpio = of_get_named_gpio_flags(np, "pinctrl-assert-gpios", + index, &flags); + if (gpio < 0) { + if (gpio == -EPROBE_DEFER) + return gpio; + break; /* End of the phandle list */ + } + + if (!gpio_is_valid(gpio)) + return -EINVAL; + + ret = devm_gpio_request_one(p->dev, gpio, GPIOF_OUT_INIT_LOW, + NULL); + if (ret < 0) + return ret; + + if (flags & OF_GPIO_ACTIVE_LOW) + continue; + + if (gpio_cansleep(gpio)) + gpio_set_value_cansleep(gpio, 1); + else + gpio_set_value(gpio, 1); + } + + return 0; +} + int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev) { struct device_node *np = p->dev->of_node; @@ -216,6 +257,12 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev) return 0; } + ret = dt_gpio_assert_pinctrl(p); + if (ret) { + dev_dbg(p->dev, "failed to assert pinctrl setting: %d\n", ret); + return ret; + } + /* We may store pointers to property names within the node */ of_node_get(np); |