summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/devicetree.c
diff options
context:
space:
mode:
authorFabio Estevam <fabio.estevam@nxp.com>2018-06-07 12:51:33 -0400
committerLinus Walleij <linus.walleij@linaro.org>2018-06-18 01:55:56 -0400
commitbc3322bc166a2905bc91f774d7b22773dc7c063a (patch)
tree6deff3168fb1eb7b4a6dd64e885c8793c057f429 /drivers/pinctrl/devicetree.c
parentfb7298e1669ee84aa76f3483c91f1de4814aac11 (diff)
pinctrl: devicetree: Fix pctldev pointer overwrite
Commit b89405b6102f ("pinctrl: devicetree: Fix dt_to_map_one_config handling of hogs") causes the pinctrl hog pins to not get initialized on i.MX platforms leaving them with the IOMUX settings untouched. This causes several regressions on i.MX such as: - OV5640 camera driver can not be probed anymore on imx6qdl-sabresd because the camera clock pin is in a pinctrl_hog group and since its pinctrl initialization is skipped, the camera clock is kept in GPIO functionality instead of CLK_CKO function. - Audio stopped working on imx6qdl-wandboard and imx53-qsb for the same reason. Richard Fitzgerald explains the problem: "I see the bug. If the hog node isn't a 1st level child of the pinctrl parent node it will go around the for(;;) loop again but on the first pass I overwrite pctldev with the result of get_pinctrl_dev_from_of_node() so it doesn't point to the pinctrl driver any more." Fix the issue by stashing the original pctldev so it doesn't get overwritten. Fixes: b89405b6102f ("pinctrl: devicetree: Fix dt_to_map_one_config handling of hogs") Cc: <stable@vger.kernel.org> Reported-by: Mika Penttilä <mika.penttila@nextfour.com> Reported-by: Steve Longerbeam <slongerbeam@gmail.com> Suggested-by: Richard Fitzgerald <rf@opensource.cirrus.com> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com> Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com> Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/devicetree.c')
-rw-r--r--drivers/pinctrl/devicetree.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index b601039d6c69..c4aa411f5935 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -101,10 +101,11 @@ struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
101} 101}
102 102
103static int dt_to_map_one_config(struct pinctrl *p, 103static int dt_to_map_one_config(struct pinctrl *p,
104 struct pinctrl_dev *pctldev, 104 struct pinctrl_dev *hog_pctldev,
105 const char *statename, 105 const char *statename,
106 struct device_node *np_config) 106 struct device_node *np_config)
107{ 107{
108 struct pinctrl_dev *pctldev = NULL;
108 struct device_node *np_pctldev; 109 struct device_node *np_pctldev;
109 const struct pinctrl_ops *ops; 110 const struct pinctrl_ops *ops;
110 int ret; 111 int ret;
@@ -123,8 +124,10 @@ static int dt_to_map_one_config(struct pinctrl *p,
123 return -EPROBE_DEFER; 124 return -EPROBE_DEFER;
124 } 125 }
125 /* If we're creating a hog we can use the passed pctldev */ 126 /* If we're creating a hog we can use the passed pctldev */
126 if (pctldev && (np_pctldev == p->dev->of_node)) 127 if (hog_pctldev && (np_pctldev == p->dev->of_node)) {
128 pctldev = hog_pctldev;
127 break; 129 break;
130 }
128 pctldev = get_pinctrl_dev_from_of_node(np_pctldev); 131 pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
129 if (pctldev) 132 if (pctldev)
130 break; 133 break;