From: Linus Walleij <redacted>
If a device have sleep and idle states in addition to the
default state, look up these in the core and stash them in
the pinctrl state container.
Add accessor functions for pinctrl consumers to put the pins
into "default", "sleep" and "idle" states passing nothing but
the struct device * affected.
Solution suggested by Kevin Hilman, Mark Brown and Dmitry
Torokhov in response to a patch series from Hebbar
Gururaja.
Cc: Hebbar Gururaja <redacted>
Cc: Mark Brown <broonie@kernel.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Kevin Hilman <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Stephen Warren <redacted>
Cc: Wolfram Sang <redacted>
Signed-off-by: Linus Walleij <redacted>
---
I'm seeking Gregs ACK on this in the end, so we can take this
in through the pinctrl tree. But first let's review!
---
drivers/base/pinctrl.c | 19 +++++++++++++
drivers/pinctrl/core.c | 61 ++++++++++++++++++++++++++++++++++++++++
include/linux/pinctrl/consumer.h | 34 ++++++++++++++++++++++
include/linux/pinctrl/devinfo.h | 4 +++
4 files changed, 118 insertions(+)
@@ -48,6 +48,25 @@ int pinctrl_bind_pins(struct device *dev)gotocleanup_get;}+#ifdef CONFIG_PM+/*+*Ifpowermanagementisenabled,wealsolookfortheoptional+*sleepandidlepinstates,withsemanticsasdefinedin+*<linux/pinctrl/pinctrl-state.h>+*/+dev->pins->sleep_state=pinctrl_lookup_state(dev->pins->p,+PINCTRL_STATE_SLEEP);+if(IS_ERR(dev->pins->sleep_state))+/* Not supplying this state is perfectly legal */+dev_dbg(dev,"no sleep pinctrl state\n");++dev->pins->idle_state=pinctrl_lookup_state(dev->pins->p,+PINCTRL_STATE_IDLE);+if(IS_ERR(dev->pins->idle_state))+/* Not supplying this state is perfectly legal */+dev_dbg(dev,"no idle pinctrl state\n");+#endif+return0;/*
@@ -1196,6 +1196,67 @@ int pinctrl_force_default(struct pinctrl_dev *pctldev)}EXPORT_SYMBOL_GPL(pinctrl_force_default);+#ifdef CONFIG_PM++/**+*pinctrl_pm_select_default_state()-selectdefaultpinctrlstateforPM+*@dev:devicetoselectdefaultstatefor+*/+intpinctrl_pm_select_default_state(structdevice*dev)+{+structdev_pin_info*pins=dev->pins;+intret;++if(!pins)+return0;+if(IS_ERR(pins->default_state))+return0;/* No default state */+ret=pinctrl_select_state(pins->p,pins->default_state);+if(ret)+dev_err(dev,"failed to activate default pinctrl state\n");+returnret;+}++/**+*pinctrl_pm_select_sleep_state()-selectsleeppinctrlstateforPM+*@dev:devicetoselectsleepstatefor+*/+intpinctrl_pm_select_sleep_state(structdevice*dev)+{+structdev_pin_info*pins=dev->pins;+intret;++if(!pins)+return0;+if(IS_ERR(pins->sleep_state))+return0;/* No default state */+ret=pinctrl_select_state(pins->p,pins->sleep_state);+if(ret)+dev_err(dev,"failed to activate sleep pinctrl state\n");+returnret;+}++/**+*pinctrl_pm_select_idle_state()-selectidlepinctrlstateforPM+*@dev:devicetoselectidlestatefor+*/+intpinctrl_pm_select_idle_state(structdevice*dev)+{+structdev_pin_info*pins=dev->pins;+intret;++if(!pins)+return0;+if(IS_ERR(pins->idle_state))+return0;/* No default state */+ret=pinctrl_select_state(pins->p,pins->idle_state);+if(ret)+dev_err(dev,"failed to activate idle pinctrl state\n");+returnret;+}++#endif+#ifdef CONFIG_DEBUG_FSstaticintpinctrl_pins_show(structseq_file*s,void*what)
From: Wolfram Sang <hidden> Date: 2013-06-05 14:01:58
On Wed, Jun 05, 2013 at 03:44:31PM +0200, Linus Walleij wrote:
From: Linus Walleij <redacted>
If a device have sleep and idle states in addition to the
default state, look up these in the core and stash them in
the pinctrl state container.
Add accessor functions for pinctrl consumers to put the pins
into "default", "sleep" and "idle" states passing nothing but
the struct device * affected.
Solution suggested by Kevin Hilman, Mark Brown and Dmitry
Torokhov in response to a patch series from Hebbar
Gururaja.
Cc: Hebbar Gururaja <redacted>
Cc: Mark Brown <broonie@kernel.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Kevin Hilman <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Stephen Warren <redacted>
Cc: Wolfram Sang <redacted>
Signed-off-by: Linus Walleij <redacted>
Some nits:
+ if (IS_ERR(pins->sleep_state))
+ return 0; /* No default state */
Comment wants to say "sleep state"?
+ ret = pinctrl_select_state(pins->p, pins->sleep_state);
+ if (ret)
+ dev_err(dev, "failed to activate sleep pinctrl state\n");
Better say "pinctrl sleep state"?
+ if (IS_ERR(pins->idle_state))
+ return 0; /* No default state */
+ ret = pinctrl_select_state(pins->p, pins->idle_state);
+ if (ret)
+ dev_err(dev, "failed to activate idle pinctrl state\n");
From: Linus Walleij <redacted>
This augments the PL011 UART driver to utilize the new pinctrl
core PM helpers to transition the driver to default and sleep
states, cutting away some boilerplate code.
Cc: Hebbar Gururaja <redacted>
Cc: Mark Brown <broonie@kernel.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Kevin Hilman <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Stephen Warren <redacted>
Cc: Wolfram Sang <redacted>
Signed-off-by: Linus Walleij <redacted>
---
I'm seeking Greg's ACK on this as well so we can take the
whole refactoring through the pinctrl tree.
---
drivers/tty/serial/amba-pl011.c | 42 +++--------------------------------------
1 file changed, 3 insertions(+), 39 deletions(-)
@@ -151,10 +151,6 @@ struct pl011_dmatx_data {structuart_amba_port{structuart_portport;structclk*clk;-/* Two optional pin states - default & sleep */-structpinctrl*pinctrl;-structpinctrl_state*pins_default;-structpinctrl_state*pins_sleep;conststructvendor_data*vendor;unsignedintdmacr;/* dma control reg */unsignedintim;/* interrupt mask */
@@ -1480,12 +1476,7 @@ static int pl011_hwinit(struct uart_port *port)intretval;/* Optionaly enable pins to be muxed in and configured */-if(!IS_ERR(uap->pins_default)){-retval=pinctrl_select_state(uap->pinctrl,uap->pins_default);-if(retval)-dev_err(port->dev,-"could not set default pins\n");-}+pinctrl_pm_select_default_state(port->dev);/**Trytoenabletheclockproducer.
@@ -1654,13 +1644,7 @@ static void pl011_shutdown(struct uart_port *port)*/clk_disable_unprepare(uap->clk);/* Optionally let pins go into sleep states */-if(!IS_ERR(uap->pins_sleep)){-retval=pinctrl_select_state(uap->pinctrl,uap->pins_sleep);-if(retval)-dev_err(port->dev,-"could not set pins to sleep state\n");-}-+pinctrl_pm_select_sleep_state(port->dev);if(uap->port.dev->platform_data){structamba_pl011_data*plat;
@@ -2013,12 +1997,7 @@ static int __init pl011_console_setup(struct console *co, char *options)return-ENODEV;/* Allow pins to be muxed in and configured */-if(!IS_ERR(uap->pins_default)){-ret=pinctrl_select_state(uap->pinctrl,uap->pins_default);-if(ret)-dev_err(uap->port.dev,-"could not set default pins\n");-}+pinctrl_pm_select_default_state(uap->port.dev);ret=clk_prepare(uap->clk);if(ret)
@@ -2132,21 +2111,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)gotoout;}-uap->pinctrl=devm_pinctrl_get(&dev->dev);-if(IS_ERR(uap->pinctrl)){-ret=PTR_ERR(uap->pinctrl);-gotoout;-}-uap->pins_default=pinctrl_lookup_state(uap->pinctrl,-PINCTRL_STATE_DEFAULT);-if(IS_ERR(uap->pins_default))-dev_err(&dev->dev,"could not get default pinstate\n");--uap->pins_sleep=pinctrl_lookup_state(uap->pinctrl,-PINCTRL_STATE_SLEEP);-if(IS_ERR(uap->pins_sleep))-dev_dbg(&dev->dev,"could not get sleep pinstate\n");-uap->clk=devm_clk_get(&dev->dev,NULL);if(IS_ERR(uap->clk)){ret=PTR_ERR(uap->clk);
From: Linus Walleij <redacted>
This utilize the new pinctrl core PM helpers to transition
the driver to "sleep" and "idle" states, cutting away some
boilerplate code.
Cc: Hebbar Gururaja <redacted>
Cc: Mark Brown <broonie@kernel.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Kevin Hilman <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Stephen Warren <redacted>
Cc: Wolfram Sang <redacted>
Signed-off-by: Linus Walleij <redacted>
---
I'm seeking Wolfram's ACK on this to take it through the
pinctrl tree in the end.
---
drivers/i2c/busses/i2c-nomadik.c | 90 +++++-----------------------------------
1 file changed, 10 insertions(+), 80 deletions(-)
@@ -165,11 +161,6 @@ struct nmk_i2c_dev {intstop;structcompletionxfer_complete;intresult;-/* Three pin states - default, idle & sleep */-structpinctrl*pinctrl;-structpinctrl_state*pins_default;-structpinctrl_state*pins_idle;-structpinctrl_state*pins_sleep;boolbusy;};
@@ -645,13 +636,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,}/* Optionaly enable pins to be muxed in and configured */-if(!IS_ERR(dev->pins_default)){-status=pinctrl_select_state(dev->pinctrl,-dev->pins_default);-if(status)-dev_err(&dev->adev->dev,-"could not set default pins\n");-}+pinctrl_pm_select_default_state(&dev->adev->dev);status=init_hw(dev);if(status)
@@ -681,13 +666,7 @@ out:clk_disable_unprepare(dev->clk);out_clk:/* Optionally let pins go into idle state */-if(!IS_ERR(dev->pins_idle)){-status=pinctrl_select_state(dev->pinctrl,-dev->pins_idle);-if(status)-dev_err(&dev->adev->dev,-"could not set pins to idle state\n");-}+pinctrl_pm_select_idle_state(&dev->adev->dev);pm_runtime_put_sync(&dev->adev->dev);
@@ -882,41 +861,22 @@ static int nmk_i2c_suspend(struct device *dev){structamba_device*adev=to_amba_device(dev);structnmk_i2c_dev*nmk_i2c=amba_get_drvdata(adev);-intret;if(nmk_i2c->busy)return-EBUSY;-if(!IS_ERR(nmk_i2c->pins_sleep)){-ret=pinctrl_select_state(nmk_i2c->pinctrl,-nmk_i2c->pins_sleep);-if(ret)-dev_err(dev,"could not set pins to sleep state\n");-}+pinctrl_pm_select_sleep_state(dev);return0;}staticintnmk_i2c_resume(structdevice*dev){-structamba_device*adev=to_amba_device(dev);-structnmk_i2c_dev*nmk_i2c=amba_get_drvdata(adev);-intret;-/* First go to the default state */-if(!IS_ERR(nmk_i2c->pins_default)){-ret=pinctrl_select_state(nmk_i2c->pinctrl,-nmk_i2c->pins_default);-if(ret)-dev_err(dev,"could not set pins to default state\n");-}+pinctrl_pm_select_default_state(dev);/* Then let's idle the pins until the next transfer happens */-if(!IS_ERR(nmk_i2c->pins_idle)){-ret=pinctrl_select_state(nmk_i2c->pinctrl,-nmk_i2c->pins_idle);-if(ret)-dev_err(dev,"could not set pins to idle state\n");-}+pinctrl_pm_select_idle_state(dev);+return0;}#else
@@ -1004,39 +964,10 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)dev->adev=adev;amba_set_drvdata(adev,dev);-dev->pinctrl=devm_pinctrl_get(&adev->dev);-if(IS_ERR(dev->pinctrl)){-ret=PTR_ERR(dev->pinctrl);-gotoerr_pinctrl;-}--dev->pins_default=pinctrl_lookup_state(dev->pinctrl,-PINCTRL_STATE_DEFAULT);-if(IS_ERR(dev->pins_default)){-dev_err(&adev->dev,"could not get default pinstate\n");-}else{-ret=pinctrl_select_state(dev->pinctrl,-dev->pins_default);-if(ret)-dev_dbg(&adev->dev,"could not set default pinstate\n");-}--dev->pins_idle=pinctrl_lookup_state(dev->pinctrl,-PINCTRL_STATE_IDLE);-if(IS_ERR(dev->pins_idle)){-dev_dbg(&adev->dev,"could not get idle pinstate\n");-}else{-/* If possible, let's go to idle until the first transfer */-ret=pinctrl_select_state(dev->pinctrl,-dev->pins_idle);-if(ret)-dev_dbg(&adev->dev,"could not set idle pinstate\n");-}--dev->pins_sleep=pinctrl_lookup_state(dev->pinctrl,-PINCTRL_STATE_SLEEP);-if(IS_ERR(dev->pins_sleep))-dev_dbg(&adev->dev,"could not get sleep pinstate\n");+/* Select default pin state */+pinctrl_pm_select_default_state(&adev->dev);+/* If possible, let's go to idle until the first transfer */+pinctrl_pm_select_idle_state(&adev->dev);dev->virtbase=ioremap(adev->res.start,resource_size(&adev->res));if(!dev->virtbase){
From: Mark Brown <broonie@kernel.org> Date: 2013-06-05 14:47:41
On Wed, Jun 05, 2013 at 03:44:31PM +0200, Linus Walleij wrote:
From: Linus Walleij <redacted>
If a device have sleep and idle states in addition to the
default state, look up these in the core and stash them in
the pinctrl state container.
Add accessor functions for pinctrl consumers to put the pins
into "default", "sleep" and "idle" states passing nothing but
the struct device * affected.
From: Stephen Warren <hidden> Date: 2013-06-05 17:22:55
On 06/05/2013 07:44 AM, Linus Walleij wrote:
From: Linus Walleij <redacted>
If a device have sleep and idle states in addition to the
default state, look up these in the core and stash them in
the pinctrl state container.
Add accessor functions for pinctrl consumers to put the pins
into "default", "sleep" and "idle" states passing nothing but
the struct device * affected.
Solution suggested by Kevin Hilman, Mark Brown and Dmitry
Torokhov in response to a patch series from Hebbar
Gururaja.
The implementation of those 3 functions is basically identical. I'd be
inclined to move it to a helper function, and just pass (dev,
pins->xxx_state) to it.
On Wed, Jun 05, 2013 at 03:44:31PM +0200, Linus Walleij wrote:
From: Linus Walleij <redacted>
If a device have sleep and idle states in addition to the
default state, look up these in the core and stash them in
the pinctrl state container.
Add accessor functions for pinctrl consumers to put the pins
into "default", "sleep" and "idle" states passing nothing but
the struct device * affected.
Solution suggested by Kevin Hilman, Mark Brown and Dmitry
Torokhov in response to a patch series from Hebbar
Gururaja.
Cc: Hebbar Gururaja <redacted>
Cc: Mark Brown <broonie@kernel.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Kevin Hilman <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Stephen Warren <redacted>
Cc: Wolfram Sang <redacted>
Signed-off-by: Linus Walleij <redacted>
---
I'm seeking Gregs ACK on this in the end, so we can take this
in through the pinctrl tree. But first let's review!
On Wed, Jun 05, 2013 at 03:44:32PM +0200, Linus Walleij wrote:
From: Linus Walleij <redacted>
This augments the PL011 UART driver to utilize the new pinctrl
core PM helpers to transition the driver to default and sleep
states, cutting away some boilerplate code.
Cc: Hebbar Gururaja <redacted>
Cc: Mark Brown <broonie@kernel.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Kevin Hilman <redacted>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Stephen Warren <redacted>
Cc: Wolfram Sang <redacted>
Signed-off-by: Linus Walleij <redacted>
---
I'm seeking Greg's ACK on this as well so we can take the
whole refactoring through the pinctrl tree.
The implementation of those 3 functions is basically identical. I'd be
inclined to move it to a helper function, and just pass (dev,
pins->xxx_state) to it.
Point taken, but as the comments only affect pinctrl/core.c
and I got so many nice ACKs on the patch, I'll apply this
and think about a refactoring patch only hitting the core
in drivers/pinctrl/* to nice this up. (Need this infrastructure
in place for the OMAP work now I think...)
Yours,
Linus Walleij
The implementation of those 3 functions is basically identical. I'd be
inclined to move it to a helper function, and just pass (dev,
pins->xxx_state) to it.
Just to follow up on this now that I'm adding one more state.
I tried to create a refactoring patch for this but couldn't come
up with anything apropriate along the lines above. For example
this function:
int pinctrl_pm_select_default_state(struct device *dev)
{
struct dev_pin_info *pins = dev->pins;
int ret;
if (!pins)
return 0;
if (IS_ERR(pins->default_state))
return 0; /* No default state */
ret = pinctrl_select_state(pins->p, pins->default_state);
if (ret)
dev_err(dev, "failed to activate default pinctrl state\n");
return ret;
}
Would be refactored into something like this:
static int pinctrl_pm_select_state(struct device *dev, struct pinctrl_state *s)
{
struct dev_pin_info *pins = dev->pins;
if (IS_ERR(s))
return 0;
return pinctrl_select_state(pins->p, s);
}
int pinctrl_pm_select_default_state(struct device *dev)
{
struct dev_pin_info *pins = dev->pins;
int ret;
if (!pins)
return 0;
if (IS_ERR(pins->default_state))
return 0; /* No default state */
ret = pinctrl_pm_select_state(dev, pins->default_state);
if (ret)
dev_err(dev, "failed to activate default pinctrl state\n");
return ret;
}
That is not any elegant, I can cut down the lines by removing
debug messages but still we're dereferencing the pins twice and other
ugliness like that. Also pinctrl_pm_select_state() becomes more and more
a NULL wrapper around pinctrl_select_state() itself. If you have some other
suggestion or a patch ... I just can't see any elegant refactoring here.
Yours,
Linus Walleij
The implementation of those 3 functions is basically identical. I'd be
inclined to move it to a helper function, and just pass (dev,
pins->xxx_state) to it.
Just to follow up on this now that I'm adding one more state.
I tried to create a refactoring patch for this but couldn't come
up with anything apropriate along the lines above. For example
this function:
...
Don't you just want something very roughly like:
int pinctrl_pm_select_xxx_state(struct device *dev,
unsigned long offset, char *name)
{
struct dev_pin_info *pins = dev->pins;
struct pinctrl_state **s = (void *)(((char *)pins) + offset)
int ret;
if (!pins)
return 0;
if (IS_ERR(*s))
return 0; /* No default state */
ret = pinctrl_select_state(pins->p, *s);
if (ret)
dev_err(dev, "failed to activate %s pinctrl state\n",
name);
return ret;
}
int pinctrl_pm_select_default_state(struct device *dev)
{
return pinctrl_pm_select_xxx_state(dev,
offsetof(struct dev_pin_info, default_state),
"default");
}
Argh that seems a bit too esoteric to save these few
lines, maybe it's me being too stupid to parse this
but it makes the code less maintainable for the pinctrl
maintainer atleast so will not happen right now.
But it is clever still. :-)
Yours,
Linus Walleij
The three functions pinctrl_pm_select_default_state,
pinctrl_pm_select_sleep_state, and pinctrl_pm_select_idle_state
are used in drivers that can be loadable modules, and should
be exported.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
On Mon, Jun 17, 2013 at 5:12 PM, Arnd Bergmann [off-list ref] wrote:
The three functions pinctrl_pm_select_default_state,
pinctrl_pm_select_sleep_state, and pinctrl_pm_select_idle_state
are used in drivers that can be loadable modules, and should
be exported.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
That's right, sorry for missing this :-(
Patch applied!
Yours,
Linus Walleij