summaryrefslogtreecommitdiff
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@freescale.com>2013-07-15 16:31:53 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:20:42 +0300
commitf60fa4b34d642e7dde3b48b8412eede1bcf13ead (patch)
tree4b129ce7fbef961b0c475adbd04ffa4b0011fa0c /drivers/pinctrl
parent20de9792e12c4898c0014e06650c7c54218a9df9 (diff)
MLK-11749: pinctrl: support pinctrl setting assertion via gpios
It's pretty common that on some reference design or validation boards, one pin could be used by two devices on board, and the pin route is controlled by a GPIO. So to assert the pin for given device, not only the pinmux controller in SoC needs to be set up properly but also the GPIO needs to be pulled up/down. The patch adds support of a device tree property "pinctrl-assert-gpios" under client device node. It plays pretty much like a board level pin multiplexer, and steers the pin route by controlling the GPIOs. When client device has the property represent in its node, pinctrl device tree mapping function will firstly pull up/down the GPIOs to assert the pins for the device at board level. [shawn.guo: cherry-pick commit e5a718edab82 from imx_3.10.y] Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/devicetree.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index 54dad89fc9bf..1f890267cb72 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
@@ -166,6 +167,43 @@ static int dt_remember_dummy_state(struct pinctrl *p, const char *statename)
return dt_remember_or_free_map(p, statename, NULL, map, 1);
}
+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)
+ 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 device_node *np = p->dev->of_node;
@@ -186,6 +224,12 @@ int pinctrl_dt_to_map(struct pinctrl *p)
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);