Late pin control fix for v4.11:
An issue was detected with pin control hos on the Freescale i.MX after the refactorings for more general group and function handling. We now have the proper fix for this. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJY6LkVAAoJEEEQszewGV1znr0P/17ltjCxoR9qYkMsreCs6FIk BSCx2UEmYt03WKizyj1M1/YKP2NYcngp8TXsRsMyi7vqMjVoL1BsPo8BjFGNI7lq znLyUWuP3xo9Y/naagxkfLw5TbfNF4hyL0JBchvg6ox1Kt7Z47Sed7KDXtB5QQdJ WbU4Hdo6ZG/nvl3LAc1wivF3qtnBsxIzx6CMiR2dyiOmLGADHj7jiJ70BuRMyTlo 4no0Cfm93lnPo1ccNMVZY2Rqt09XhwPppewL7j2IqOin/Kr88qWKwdOheCu/Ojsp GJfTgKjVpieKW2PjkIiDDSiTKKkUvVmzEQz+qqXozjQSwwKtJ106xZ8fW+d5xFeY EJ3jsQtKdmI3q7M0mbYpfK0vM9C1MKMg71CJt8pvbtg2NXfAfLsA9BioVOGKrOua upy6RCMDhoBRh4jRjd5DcJPKRq45m/toVSZ+tfS1Nur2k3tXd41CI3y6D+wUlz95 oq8QW2bWsC52vLXS6qywJkUM7CQiBs61FIryf84YC7mE4AqRFJpCZfBqrUYLkctN 5OHF++wu6tEXYfgR6rtWY+c26xgc6PK/rALtYvzDC4o72Z0xQLlQqFnf6hGAp3Dl eosuW5TUvnlFUEMF3CEQwVHj3awpgdo6X4UnYDIxZDRU4R/vODH46s1H719TMIWx ZBztLllUHpn57LVRvudT =06og -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
c3df1c7c36
|
@ -77,9 +77,15 @@ static struct pinctrl_desc foo_desc = {
|
|||
|
||||
int __init foo_probe(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
struct pinctrl_dev *pctl;
|
||||
|
||||
return pinctrl_register_and_init(&foo_desc, <PARENT>, NULL, &pctl);
|
||||
error = pinctrl_register_and_init(&foo_desc, <PARENT>, NULL, &pctl);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return pinctrl_enable(pctl);
|
||||
}
|
||||
|
||||
To enable the pinctrl subsystem and the subgroups for PINMUX and PINCONF and
|
||||
|
|
|
@ -2010,29 +2010,57 @@ out_err:
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int pinctrl_create_and_start(struct pinctrl_dev *pctldev)
|
||||
static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
pctldev->p = create_pinctrl(pctldev->dev, pctldev);
|
||||
if (!IS_ERR(pctldev->p)) {
|
||||
kref_get(&pctldev->p->users);
|
||||
pctldev->hog_default =
|
||||
pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR(pctldev->hog_default)) {
|
||||
dev_dbg(pctldev->dev,
|
||||
"failed to lookup the default state\n");
|
||||
} else {
|
||||
if (pinctrl_select_state(pctldev->p,
|
||||
pctldev->hog_default))
|
||||
dev_err(pctldev->dev,
|
||||
"failed to select default state\n");
|
||||
}
|
||||
if (PTR_ERR(pctldev->p) == -ENODEV) {
|
||||
dev_dbg(pctldev->dev, "no hogs found\n");
|
||||
|
||||
pctldev->hog_sleep =
|
||||
pinctrl_lookup_state(pctldev->p,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(pctldev->hog_sleep))
|
||||
dev_dbg(pctldev->dev,
|
||||
"failed to lookup the sleep state\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IS_ERR(pctldev->p)) {
|
||||
dev_err(pctldev->dev, "error claiming hogs: %li\n",
|
||||
PTR_ERR(pctldev->p));
|
||||
|
||||
return PTR_ERR(pctldev->p);
|
||||
}
|
||||
|
||||
kref_get(&pctldev->p->users);
|
||||
pctldev->hog_default =
|
||||
pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
|
||||
if (IS_ERR(pctldev->hog_default)) {
|
||||
dev_dbg(pctldev->dev,
|
||||
"failed to lookup the default state\n");
|
||||
} else {
|
||||
if (pinctrl_select_state(pctldev->p,
|
||||
pctldev->hog_default))
|
||||
dev_err(pctldev->dev,
|
||||
"failed to select default state\n");
|
||||
}
|
||||
|
||||
pctldev->hog_sleep =
|
||||
pinctrl_lookup_state(pctldev->p,
|
||||
PINCTRL_STATE_SLEEP);
|
||||
if (IS_ERR(pctldev->hog_sleep))
|
||||
dev_dbg(pctldev->dev,
|
||||
"failed to lookup the sleep state\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pinctrl_enable(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = pinctrl_claim_hogs(pctldev);
|
||||
if (error) {
|
||||
dev_err(pctldev->dev, "could not claim hogs: %i\n",
|
||||
error);
|
||||
mutex_destroy(&pctldev->mutex);
|
||||
kfree(pctldev);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
mutex_lock(&pinctrldev_list_mutex);
|
||||
|
@ -2043,6 +2071,7 @@ static int pinctrl_create_and_start(struct pinctrl_dev *pctldev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_enable);
|
||||
|
||||
/**
|
||||
* pinctrl_register() - register a pin controller device
|
||||
|
@ -2065,25 +2094,30 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
|||
if (IS_ERR(pctldev))
|
||||
return pctldev;
|
||||
|
||||
error = pinctrl_create_and_start(pctldev);
|
||||
if (error) {
|
||||
mutex_destroy(&pctldev->mutex);
|
||||
kfree(pctldev);
|
||||
|
||||
error = pinctrl_enable(pctldev);
|
||||
if (error)
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
return pctldev;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_register);
|
||||
|
||||
/**
|
||||
* pinctrl_register_and_init() - register and init pin controller device
|
||||
* @pctldesc: descriptor for this pin controller
|
||||
* @dev: parent device for this pin controller
|
||||
* @driver_data: private pin controller data for this pin controller
|
||||
* @pctldev: pin controller device
|
||||
*
|
||||
* Note that pinctrl_enable() still needs to be manually called after
|
||||
* this once the driver is ready.
|
||||
*/
|
||||
int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
|
||||
struct device *dev, void *driver_data,
|
||||
struct pinctrl_dev **pctldev)
|
||||
{
|
||||
struct pinctrl_dev *p;
|
||||
int error;
|
||||
|
||||
p = pinctrl_init_controller(pctldesc, dev, driver_data);
|
||||
if (IS_ERR(p))
|
||||
|
@ -2097,15 +2131,6 @@ int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
|
|||
*/
|
||||
*pctldev = p;
|
||||
|
||||
error = pinctrl_create_and_start(p);
|
||||
if (error) {
|
||||
mutex_destroy(&p->mutex);
|
||||
kfree(p);
|
||||
*pctldev = NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinctrl_register_and_init);
|
||||
|
|
|
@ -790,7 +790,7 @@ int imx_pinctrl_probe(struct platform_device *pdev,
|
|||
|
||||
dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
|
||||
|
||||
return 0;
|
||||
return pinctrl_enable(ipctl->pctl);
|
||||
|
||||
free:
|
||||
imx_free_resources(ipctl);
|
||||
|
|
|
@ -1781,7 +1781,7 @@ static int pcs_probe(struct platform_device *pdev)
|
|||
dev_info(pcs->dev, "%i pins at pa %p size %u\n",
|
||||
pcs->desc.npins, pcs->base, pcs->size);
|
||||
|
||||
return 0;
|
||||
return pinctrl_enable(pcs->pctl);
|
||||
|
||||
free:
|
||||
pcs_free_resources(pcs);
|
||||
|
|
|
@ -816,6 +816,13 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
|
|||
pmx->pctl_desc.pins = pmx->pins;
|
||||
pmx->pctl_desc.npins = pfc->info->nr_pins;
|
||||
|
||||
return devm_pinctrl_register_and_init(pfc->dev, &pmx->pctl_desc, pmx,
|
||||
&pmx->pctl);
|
||||
ret = devm_pinctrl_register_and_init(pfc->dev, &pmx->pctl_desc, pmx,
|
||||
&pmx->pctl);
|
||||
if (ret) {
|
||||
dev_err(pfc->dev, "could not register: %i\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return pinctrl_enable(pmx->pctl);
|
||||
}
|
||||
|
|
|
@ -893,6 +893,8 @@ static int ti_iodelay_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, iod);
|
||||
|
||||
return pinctrl_enable(iod->pctl);
|
||||
|
||||
exit_out:
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
|
|
|
@ -145,8 +145,9 @@ struct pinctrl_desc {
|
|||
extern int pinctrl_register_and_init(struct pinctrl_desc *pctldesc,
|
||||
struct device *dev, void *driver_data,
|
||||
struct pinctrl_dev **pctldev);
|
||||
extern int pinctrl_enable(struct pinctrl_dev *pctldev);
|
||||
|
||||
/* Please use pinctrl_register_and_init() instead */
|
||||
/* Please use pinctrl_register_and_init() and pinctrl_enable() instead */
|
||||
extern struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
|
||||
struct device *dev, void *driver_data);
|
||||
|
||||
|
|
Loading…
Reference in a new issue