aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2013-01-22 12:56:14 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-01-23 10:39:51 -0500
commitab78029ecc347debbd737f06688d788bd9d60c1d (patch)
treeaffc1f843abc1897ccf2723cf077be343c2845e2 /drivers/pinctrl
parent684697cbbcd076b8fde78d8863e341700533b542 (diff)
drivers/pinctrl: grab default handles from device core
This makes the device core auto-grab the pinctrl handle and set the "default" (PINCTRL_STATE_DEFAULT) state for every device that is present in the device model right before probe. This will account for the lion's share of embedded silicon devcies. A modification of the semantics for pinctrl_get() is also done: previously if the pinctrl handle for a certain device was already taken, the pinctrl core would return an error. Now, since the core may have already default-grabbed the handle and set its state to "default", if the handle was already taken, this will be disregarded and the located, previously instanitated handle will be returned to the caller. This way all code in drivers explicitly requesting their pinctrl handlers will still be functional, and drivers that want to explicitly retrieve and switch their handles can still do that. But if the desired functionality is just boilerplate of this type in the probe() function: struct pinctrl *p; p = devm_pinctrl_get_select_default(&dev); if (IS_ERR(p)) { if (PTR_ERR(p) == -EPROBE_DEFER) return -EPROBE_DEFER; dev_warn(&dev, "no pinctrl handle\n"); } The discussion began with the addition of such boilerplate to the omap4 keypad driver: http://marc.info/?l=linux-input&m=135091157719300&w=2 A previous approach using notifiers was discussed: http://marc.info/?l=linux-kernel&m=135263661110528&w=2 This failed because it could not handle deferred probes. This patch alone does not solve the entire dilemma faced: whether code should be distributed into the drivers or if it should be centralized to e.g. a PM domain. But it solves the immediate issue of the addition of boilerplate to a lot of drivers that just want to grab the default state. As mentioned, they can later explicitly retrieve the handle and set different states, and this could as well be done by e.g. PM domains as it is only related to a certain struct device * pointer. ChangeLog v4->v5 (Stephen): - Simplified the devicecore grab code. - Deleted a piece of documentation recommending that pins be mapped to a device rather than hogged. ChangeLog v3->v4 (Linus): - Drop overzealous NULL checks. - Move kref initialization to pinctrl_create(). - Seeking Tested-by from Stephen Warren so we do not disturb the Tegra platform. - Seeking ACK on this from Greg (and others who like it) so I can merge it through the pinctrl subsystem. ChangeLog v2->v3 (Linus): - Abstain from using IS_ERR_OR_NULL() in the driver core, Russell recently sent a patch to remove it. Handle the NULL case explicitly even though it's a bogus case. - Make sure we handle probe deferral correctly in the device core file. devm_kfree() the container on error so we don't waste memory for devices without pinctrl handles. - Introduce reference counting into the pinctrl core using <linux/kref.h> so that we don't release pinctrl handles that have been obtained for two or more places. ChangeLog v1->v2 (Linus): - Only store a pointer in the device struct, and only allocate this if it's really used by the device. Cc: Felipe Balbi <balbi@ti.com> Cc: Benoit Cousson <b-cousson@ti.com> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Cc: Mitch Bradley <wmb@firmworks.com> Cc: Ulf Hansson <ulf.hansson@linaro.org> Cc: Rafael J. Wysocki <rjw@sisk.pl> Cc: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Cc: Rickard Andersson <rickard.andersson@stericsson.com> Cc: Russell King <linux@arm.linux.org.uk> Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> [swarren: fixed and simplified error-handling in pinctrl_bind_pins(), to correctly handle deferred probe. Removed admonition from docs not to use pinctrl hogs for devices] Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/core.c30
-rw-r--r--drivers/pinctrl/core.h3
2 files changed, 29 insertions, 4 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index e6373f30aeeb..5a2fe9aae20f 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -14,6 +14,7 @@
14#define pr_fmt(fmt) "pinctrl core: " fmt 14#define pr_fmt(fmt) "pinctrl core: " fmt
15 15
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/kref.h>
17#include <linux/export.h> 18#include <linux/export.h>
18#include <linux/init.h> 19#include <linux/init.h>
19#include <linux/device.h> 20#include <linux/device.h>
@@ -727,6 +728,8 @@ static struct pinctrl *create_pinctrl(struct device *dev)
727 return ERR_PTR(ret); 728 return ERR_PTR(ret);
728 } 729 }
729 730
731 kref_init(&p->users);
732
730 /* Add the pinctrl handle to the global list */ 733 /* Add the pinctrl handle to the global list */
731 list_add_tail(&p->node, &pinctrl_list); 734 list_add_tail(&p->node, &pinctrl_list);
732 735
@@ -740,9 +743,17 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev)
740 if (WARN_ON(!dev)) 743 if (WARN_ON(!dev))
741 return ERR_PTR(-EINVAL); 744 return ERR_PTR(-EINVAL);
742 745
746 /*
747 * See if somebody else (such as the device core) has already
748 * obtained a handle to the pinctrl for this device. In that case,
749 * return another pointer to it.
750 */
743 p = find_pinctrl(dev); 751 p = find_pinctrl(dev);
744 if (p != NULL) 752 if (p != NULL) {
745 return ERR_PTR(-EBUSY); 753 dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");
754 kref_get(&p->users);
755 return p;
756 }
746 757
747 return create_pinctrl(dev); 758 return create_pinctrl(dev);
748} 759}
@@ -798,13 +809,24 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
798} 809}
799 810
800/** 811/**
801 * pinctrl_put() - release a previously claimed pinctrl handle 812 * pinctrl_release() - release the pinctrl handle
813 * @kref: the kref in the pinctrl being released
814 */
815void pinctrl_release(struct kref *kref)
816{
817 struct pinctrl *p = container_of(kref, struct pinctrl, users);
818
819 pinctrl_put_locked(p, true);
820}
821
822/**
823 * pinctrl_put() - decrease use count on a previously claimed pinctrl handle
802 * @p: the pinctrl handle to release 824 * @p: the pinctrl handle to release
803 */ 825 */
804void pinctrl_put(struct pinctrl *p) 826void pinctrl_put(struct pinctrl *p)
805{ 827{
806 mutex_lock(&pinctrl_mutex); 828 mutex_lock(&pinctrl_mutex);
807 pinctrl_put_locked(p, true); 829 kref_put(&p->users, pinctrl_release);
808 mutex_unlock(&pinctrl_mutex); 830 mutex_unlock(&pinctrl_mutex);
809} 831}
810EXPORT_SYMBOL_GPL(pinctrl_put); 832EXPORT_SYMBOL_GPL(pinctrl_put);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 232a9f6db4aa..fdd350d639f6 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -9,6 +9,7 @@
9 * License terms: GNU General Public License (GPL) version 2 9 * License terms: GNU General Public License (GPL) version 2
10 */ 10 */
11 11
12#include <linux/kref.h>
12#include <linux/mutex.h> 13#include <linux/mutex.h>
13#include <linux/radix-tree.h> 14#include <linux/radix-tree.h>
14#include <linux/pinctrl/pinconf.h> 15#include <linux/pinctrl/pinconf.h>
@@ -58,6 +59,7 @@ struct pinctrl_dev {
58 * @state: the current state 59 * @state: the current state
59 * @dt_maps: the mapping table chunks dynamically parsed from device tree for 60 * @dt_maps: the mapping table chunks dynamically parsed from device tree for
60 * this device, if any 61 * this device, if any
62 * @users: reference count
61 */ 63 */
62struct pinctrl { 64struct pinctrl {
63 struct list_head node; 65 struct list_head node;
@@ -65,6 +67,7 @@ struct pinctrl {
65 struct list_head states; 67 struct list_head states;
66 struct pinctrl_state *state; 68 struct pinctrl_state *state;
67 struct list_head dt_maps; 69 struct list_head dt_maps;
70 struct kref users;
68}; 71};
69 72
70/** 73/**