aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-04-08 14:43:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-04-08 14:43:38 -0400
commitc3df1c7c36aa55fa76d77d57383af334856ab9f8 (patch)
tree2b6ee459d9559814bb5eccf9442afe2bea30f619 /drivers/pinctrl/core.c
parent894ca30cf6ddf891aa17c39a4b8d511c0a8cf2e9 (diff)
parent6118714275f0a313ecc296a87ed1af32d9691bed (diff)
Merge tag 'pinctrl-v4.11-4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control fix from Linus Walleij: "This late fix for pin control is hopefully the last I send this cycle. The problem was detected early in the v4.11 release cycle and there has been some back and forth on how to solve it. Sadly the proper fix arrives late, but at least not too late. An issue was detected with pin control on the Freescale i.MX after the refactorings for more general group and function handling. We now have the proper fix for this" * tag 'pinctrl-v4.11-4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: pinctrl: core: Fix pinctrl_register_and_init() with pinctrl_enable()
Diffstat (limited to 'drivers/pinctrl/core.c')
-rw-r--r--drivers/pinctrl/core.c97
1 files changed, 61 insertions, 36 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index d69046537b75..32822b0d9cd0 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -2010,29 +2010,57 @@ out_err:
2010 return ERR_PTR(ret); 2010 return ERR_PTR(ret);
2011} 2011}
2012 2012
2013static int pinctrl_create_and_start(struct pinctrl_dev *pctldev) 2013static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
2014{ 2014{
2015 pctldev->p = create_pinctrl(pctldev->dev, pctldev); 2015 pctldev->p = create_pinctrl(pctldev->dev, pctldev);
2016 if (!IS_ERR(pctldev->p)) { 2016 if (PTR_ERR(pctldev->p) == -ENODEV) {
2017 kref_get(&pctldev->p->users); 2017 dev_dbg(pctldev->dev, "no hogs found\n");
2018 pctldev->hog_default =
2019 pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
2020 if (IS_ERR(pctldev->hog_default)) {
2021 dev_dbg(pctldev->dev,
2022 "failed to lookup the default state\n");
2023 } else {
2024 if (pinctrl_select_state(pctldev->p,
2025 pctldev->hog_default))
2026 dev_err(pctldev->dev,
2027 "failed to select default state\n");
2028 }
2029 2018
2030 pctldev->hog_sleep = 2019 return 0;
2031 pinctrl_lookup_state(pctldev->p, 2020 }
2032 PINCTRL_STATE_SLEEP); 2021
2033 if (IS_ERR(pctldev->hog_sleep)) 2022 if (IS_ERR(pctldev->p)) {
2034 dev_dbg(pctldev->dev, 2023 dev_err(pctldev->dev, "error claiming hogs: %li\n",
2035 "failed to lookup the sleep state\n"); 2024 PTR_ERR(pctldev->p));
2025
2026 return PTR_ERR(pctldev->p);
2027 }
2028
2029 kref_get(&pctldev->p->users);
2030 pctldev->hog_default =
2031 pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
2032 if (IS_ERR(pctldev->hog_default)) {
2033 dev_dbg(pctldev->dev,
2034 "failed to lookup the default state\n");
2035 } else {
2036 if (pinctrl_select_state(pctldev->p,
2037 pctldev->hog_default))
2038 dev_err(pctldev->dev,
2039 "failed to select default state\n");
2040 }
2041
2042 pctldev->hog_sleep =
2043 pinctrl_lookup_state(pctldev->p,
2044 PINCTRL_STATE_SLEEP);
2045 if (IS_ERR(pctldev->hog_sleep))
2046 dev_dbg(pctldev->dev,
2047 "failed to lookup the sleep state\n");
2048
2049 return 0;
2050}
2051
2052int pinctrl_enable(struct pinctrl_dev *pctldev)
2053{
2054 int error;
2055
2056 error = pinctrl_claim_hogs(pctldev);
2057 if (error) {
2058 dev_err(pctldev->dev, "could not claim hogs: %i\n",
2059 error);
2060 mutex_destroy(&pctldev->mutex);
2061 kfree(pctldev);
2062
2063 return error;
2036 } 2064 }
2037 2065
2038 mutex_lock(&pinctrldev_list_mutex); 2066 mutex_lock(&pinctrldev_list_mutex);
@@ -2043,6 +2071,7 @@ static int pinctrl_create_and_start(struct pinctrl_dev *pctldev)
2043 2071
2044 return 0; 2072 return 0;
2045} 2073}
2074EXPORT_SYMBOL_GPL(pinctrl_enable);
2046 2075
2047/** 2076/**
2048 * pinctrl_register() - register a pin controller device 2077 * pinctrl_register() - register a pin controller device
@@ -2065,25 +2094,30 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
2065 if (IS_ERR(pctldev)) 2094 if (IS_ERR(pctldev))
2066 return pctldev; 2095 return pctldev;
2067 2096
2068 error = pinctrl_create_and_start(pctldev); 2097 error = pinctrl_enable(pctldev);
2069 if (error) { 2098 if (error)
2070 mutex_destroy(&pctldev->mutex);
2071 kfree(pctldev);
2072
2073 return ERR_PTR(error); 2099 return ERR_PTR(error);
2074 }
2075 2100
2076 return pctldev; 2101 return pctldev;
2077 2102
2078} 2103}
2079EXPORT_SYMBOL_GPL(pinctrl_register); 2104EXPORT_SYMBOL_GPL(pinctrl_register);
2080 2105
2106/**
2107 * pinctrl_register_and_init() - register and init pin controller device
2108 * @pctldesc: descriptor for this pin controller
2109 * @dev: parent device for this pin controller
2110 * @driver_data: private pin controller data for this pin controller
2111 * @pctldev: pin controller device
2112 *
2113 * Note that pinctrl_enable() still needs to be manually called after
2114 * this once the driver is ready.
2115 */
2081int pinctrl_register_and_init(struct pinctrl_desc *pctldesc, 2116int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
2082 struct device *dev, void *driver_data, 2117 struct device *dev, void *driver_data,
2083 struct pinctrl_dev **pctldev) 2118 struct pinctrl_dev **pctldev)
2084{ 2119{
2085 struct pinctrl_dev *p; 2120 struct pinctrl_dev *p;
2086 int error;
2087 2121
2088 p = pinctrl_init_controller(pctldesc, dev, driver_data); 2122 p = pinctrl_init_controller(pctldesc, dev, driver_data);
2089 if (IS_ERR(p)) 2123 if (IS_ERR(p))
@@ -2097,15 +2131,6 @@ int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
2097 */ 2131 */
2098 *pctldev = p; 2132 *pctldev = p;
2099 2133
2100 error = pinctrl_create_and_start(p);
2101 if (error) {
2102 mutex_destroy(&p->mutex);
2103 kfree(p);
2104 *pctldev = NULL;
2105
2106 return error;
2107 }
2108
2109 return 0; 2134 return 0;
2110} 2135}
2111EXPORT_SYMBOL_GPL(pinctrl_register_and_init); 2136EXPORT_SYMBOL_GPL(pinctrl_register_and_init);