From dc81f006fb10556411df15debaf78c23156f5db8 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 15 Jul 2013 16:31:53 +0800 Subject: [PATCH] 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 Signed-off-by: Arulpandiyan Vadivel --- .../bindings/pinctrl/pinctrl-bindings.txt | 7 +++ drivers/pinctrl/devicetree.c | 44 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt index fcd37e93ed4d..c42d8c241ad5 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt @@ -71,6 +71,13 @@ pinctrl-names: The list of names to assign states. List entry 0 defines the name for integer state ID 0, list entry 1 for state ID 1, and so on. +pinctrl-assert-gpios: + List of phandles, each pointing at a GPIO which is used by some + board design to steer pins between two peripherals on the board. + It plays like a board level pin multiplexer to choose different + functions for given pins by pulling up/down the GPIOs. See + bindings/gpio/gpio.txt for details of how to specify GPIO. + For example: /* For a client device requiring named states */ diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index 5d6d8b1e9062..d25bc9cbfc63 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -181,6 +182,43 @@ 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) + 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; @@ -201,6 +239,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);