summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Fitzgerald <rf@opensource.cirrus.com>2018-02-28 18:53:06 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-05-30 08:52:37 +0300
commit72678f7a2922a719610e076eaf9f97ddc5481d7a (patch)
tree8ae3ce67d69685f6d2dac1a3ce09ff7e24f99830
parent39c655c5edfe629fdef92efaecd85a05b958f9a2 (diff)
downloadlinux-72678f7a2922a719610e076eaf9f97ddc5481d7a.tar.xz
pinctrl: devicetree: Fix dt_to_map_one_config handling of hogs
[ Upstream commit b89405b6102fcc3746f43697b826028caa94c823 ] When dt_to_map_one_config() is called with a pinctrl_dev passed in, it should only be using this if the node being looked up is a hog. The code was always using the passed pinctrl_dev without checking whether the dt node referred to it. A pin controller can have pinctrl-n dependencies on other pin controllers in these cases: - the pin controller hardware is external, for example I2C, so needs other pin controller(s) to be setup to communicate with the hardware device. - it is a child of a composite MFD so its of_node is shared with the parent MFD and other children of that MFD. Any part of that MFD could have dependencies on other pin controllers. Because of this, dt_to_map_one_config() can't assume that if it has a pinctrl_dev passed in then the node it looks up must be a hog. It could be a reference to some other pin controller. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/pinctrl/devicetree.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index 1ff6c3573493..b601039d6c69 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -122,8 +122,10 @@ static int dt_to_map_one_config(struct pinctrl *p,
/* OK let's just assume this will appear later then */
return -EPROBE_DEFER;
}
- if (!pctldev)
- pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
+ /* If we're creating a hog we can use the passed pctldev */
+ if (pctldev && (np_pctldev == p->dev->of_node))
+ break;
+ pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
if (pctldev)
break;
/* Do not defer probing of hogs (circular loop) */