aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorStephen Warren <swarren@wwwdotorg.org>2012-03-23 12:29:46 -0400
committerLinus Walleij <linus.walleij@linaro.org>2012-04-18 07:53:10 -0400
commit57291ce295c0aca738dd284c4a9c591c09ebee71 (patch)
tree6e687f329e7adf08b5d7dcaa3d6616ff1a9b8c27 /drivers/pinctrl
parentd26bc49fa401be2b71838b6a4b387196cd12a534 (diff)
pinctrl: core device tree mapping table parsing support
During pinctrl_get(), if the client device has a device tree node, look for the common pinctrl properties there. If found, parse the referenced device tree nodes, with the help of the pinctrl drivers, and generate mapping table entries from them. During pinctrl_put(), free any results of device tree parsing. Acked-by: Dong Aisheng <dong.aisheng@linaro.org> Signed-off-by: Stephen Warren <swarren@wwwdotorg.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/core.c72
-rw-r--r--drivers/pinctrl/core.h11
-rw-r--r--drivers/pinctrl/devicetree.c249
-rw-r--r--drivers/pinctrl/devicetree.h35
5 files changed, 350 insertions, 18 deletions
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 6d4150b4eced..049c9fb39dab 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
5obj-$(CONFIG_PINCTRL) += core.o 5obj-$(CONFIG_PINCTRL) += core.o
6obj-$(CONFIG_PINMUX) += pinmux.o 6obj-$(CONFIG_PINMUX) += pinmux.o
7obj-$(CONFIG_PINCONF) += pinconf.o 7obj-$(CONFIG_PINCONF) += pinconf.o
8obj-$(CONFIG_OF) += devicetree.o
8obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o 9obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
9obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o 10obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o
10obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o 11obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index df6296c5f47b..832f71dcd8c4 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -26,6 +26,7 @@
26#include <linux/pinctrl/pinctrl.h> 26#include <linux/pinctrl/pinctrl.h>
27#include <linux/pinctrl/machine.h> 27#include <linux/pinctrl/machine.h>
28#include "core.h" 28#include "core.h"
29#include "devicetree.h"
29#include "pinmux.h" 30#include "pinmux.h"
30#include "pinconf.h" 31#include "pinconf.h"
31 32
@@ -45,7 +46,7 @@ struct pinctrl_maps {
45DEFINE_MUTEX(pinctrl_mutex); 46DEFINE_MUTEX(pinctrl_mutex);
46 47
47/* Global list of pin control devices (struct pinctrl_dev) */ 48/* Global list of pin control devices (struct pinctrl_dev) */
48static LIST_HEAD(pinctrldev_list); 49LIST_HEAD(pinctrldev_list);
49 50
50/* List of pin controller handles (struct pinctrl) */ 51/* List of pin controller handles (struct pinctrl) */
51static LIST_HEAD(pinctrl_list); 52static LIST_HEAD(pinctrl_list);
@@ -579,6 +580,13 @@ static struct pinctrl *create_pinctrl(struct device *dev)
579 } 580 }
580 p->dev = dev; 581 p->dev = dev;
581 INIT_LIST_HEAD(&p->states); 582 INIT_LIST_HEAD(&p->states);
583 INIT_LIST_HEAD(&p->dt_maps);
584
585 ret = pinctrl_dt_to_map(p);
586 if (ret < 0) {
587 kfree(p);
588 return ERR_PTR(ret);
589 }
582 590
583 devname = dev_name(dev); 591 devname = dev_name(dev);
584 592
@@ -662,6 +670,8 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
662 kfree(state); 670 kfree(state);
663 } 671 }
664 672
673 pinctrl_dt_free_maps(p);
674
665 if (inlist) 675 if (inlist)
666 list_del(&p->node); 676 list_del(&p->node);
667 kfree(p); 677 kfree(p);
@@ -787,15 +797,8 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
787} 797}
788EXPORT_SYMBOL_GPL(pinctrl_select_state); 798EXPORT_SYMBOL_GPL(pinctrl_select_state);
789 799
790/** 800int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
791 * pinctrl_register_mappings() - register a set of pin controller mappings 801 bool dup, bool locked)
792 * @maps: the pincontrol mappings table to register. This should probably be
793 * marked with __initdata so it can be discarded after boot. This
794 * function will perform a shallow copy for the mapping entries.
795 * @num_maps: the number of maps in the mapping table
796 */
797int pinctrl_register_mappings(struct pinctrl_map const *maps,
798 unsigned num_maps)
799{ 802{
800 int i, ret; 803 int i, ret;
801 struct pinctrl_maps *maps_node; 804 struct pinctrl_maps *maps_node;
@@ -851,20 +854,52 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
851 } 854 }
852 855
853 maps_node->num_maps = num_maps; 856 maps_node->num_maps = num_maps;
854 maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps, GFP_KERNEL); 857 if (dup) {
855 if (!maps_node->maps) { 858 maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps,
856 pr_err("failed to duplicate mapping table\n"); 859 GFP_KERNEL);
857 kfree(maps_node); 860 if (!maps_node->maps) {
858 return -ENOMEM; 861 pr_err("failed to duplicate mapping table\n");
862 kfree(maps_node);
863 return -ENOMEM;
864 }
865 } else {
866 maps_node->maps = maps;
859 } 867 }
860 868
861 mutex_lock(&pinctrl_mutex); 869 if (!locked)
870 mutex_lock(&pinctrl_mutex);
862 list_add_tail(&maps_node->node, &pinctrl_maps); 871 list_add_tail(&maps_node->node, &pinctrl_maps);
863 mutex_unlock(&pinctrl_mutex); 872 if (!locked)
873 mutex_unlock(&pinctrl_mutex);
864 874
865 return 0; 875 return 0;
866} 876}
867 877
878/**
879 * pinctrl_register_mappings() - register a set of pin controller mappings
880 * @maps: the pincontrol mappings table to register. This should probably be
881 * marked with __initdata so it can be discarded after boot. This
882 * function will perform a shallow copy for the mapping entries.
883 * @num_maps: the number of maps in the mapping table
884 */
885int pinctrl_register_mappings(struct pinctrl_map const *maps,
886 unsigned num_maps)
887{
888 return pinctrl_register_map(maps, num_maps, true, false);
889}
890
891void pinctrl_unregister_map(struct pinctrl_map const *map)
892{
893 struct pinctrl_maps *maps_node;
894
895 list_for_each_entry(maps_node, &pinctrl_maps, node) {
896 if (maps_node->maps == map) {
897 list_del(&maps_node->node);
898 return;
899 }
900 }
901}
902
868#ifdef CONFIG_DEBUG_FS 903#ifdef CONFIG_DEBUG_FS
869 904
870static int pinctrl_pins_show(struct seq_file *s, void *what) 905static int pinctrl_pins_show(struct seq_file *s, void *what)
@@ -1231,6 +1266,9 @@ static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
1231 !ops->get_group_pins) 1266 !ops->get_group_pins)
1232 return -EINVAL; 1267 return -EINVAL;
1233 1268
1269 if (ops->dt_node_to_map && !ops->dt_free_map)
1270 return -EINVAL;
1271
1234 return 0; 1272 return 0;
1235} 1273}
1236 1274
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 17ecf651b123..98ae8085e735 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -52,12 +52,15 @@ struct pinctrl_dev {
52 * @dev: the device using this pin control handle 52 * @dev: the device using this pin control handle
53 * @states: a list of states for this device 53 * @states: a list of states for this device
54 * @state: the current state 54 * @state: the current state
55 * @dt_maps: the mapping table chunks dynamically parsed from device tree for
56 * this device, if any
55 */ 57 */
56struct pinctrl { 58struct pinctrl {
57 struct list_head node; 59 struct list_head node;
58 struct device *dev; 60 struct device *dev;
59 struct list_head states; 61 struct list_head states;
60 struct pinctrl_state *state; 62 struct pinctrl_state *state;
63 struct list_head dt_maps;
61}; 64};
62 65
63/** 66/**
@@ -100,7 +103,8 @@ struct pinctrl_setting_configs {
100 * struct pinctrl_setting - an individual mux or config setting 103 * struct pinctrl_setting - an individual mux or config setting
101 * @node: list node for struct pinctrl_settings's @settings field 104 * @node: list node for struct pinctrl_settings's @settings field
102 * @type: the type of setting 105 * @type: the type of setting
103 * @pctldev: pin control device handling to be programmed 106 * @pctldev: pin control device handling to be programmed. Not used for
107 * PIN_MAP_TYPE_DUMMY_STATE.
104 * @data: Data specific to the setting type 108 * @data: Data specific to the setting type
105 */ 109 */
106struct pinctrl_setting { 110struct pinctrl_setting {
@@ -153,4 +157,9 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
153 return radix_tree_lookup(&pctldev->pin_desc_tree, pin); 157 return radix_tree_lookup(&pctldev->pin_desc_tree, pin);
154} 158}
155 159
160int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
161 bool dup, bool locked);
162void pinctrl_unregister_map(struct pinctrl_map const *map);
163
156extern struct mutex pinctrl_mutex; 164extern struct mutex pinctrl_mutex;
165extern struct list_head pinctrldev_list;
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
new file mode 100644
index 000000000000..5ef2feb44395
--- /dev/null
+++ b/drivers/pinctrl/devicetree.c
@@ -0,0 +1,249 @@
1/*
2 * Device tree integration for the pin control subsystem
3 *
4 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/device.h>
20#include <linux/of.h>
21#include <linux/pinctrl/pinctrl.h>
22#include <linux/slab.h>
23
24#include "core.h"
25#include "devicetree.h"
26
27/**
28 * struct pinctrl_dt_map - mapping table chunk parsed from device tree
29 * @node: list node for struct pinctrl's @dt_maps field
30 * @pctldev: the pin controller that allocated this struct, and will free it
31 * @maps: the mapping table entries
32 */
33struct pinctrl_dt_map {
34 struct list_head node;
35 struct pinctrl_dev *pctldev;
36 struct pinctrl_map *map;
37 unsigned num_maps;
38};
39
40static void dt_free_map(struct pinctrl_dev *pctldev,
41 struct pinctrl_map *map, unsigned num_maps)
42{
43 if (pctldev) {
44 struct pinctrl_ops *ops = pctldev->desc->pctlops;
45 ops->dt_free_map(pctldev, map, num_maps);
46 } else {
47 /* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
48 kfree(map);
49 }
50}
51
52void pinctrl_dt_free_maps(struct pinctrl *p)
53{
54 struct pinctrl_dt_map *dt_map, *n1;
55
56 list_for_each_entry_safe(dt_map, n1, &p->dt_maps, node) {
57 pinctrl_unregister_map(dt_map->map);
58 list_del(&dt_map->node);
59 dt_free_map(dt_map->pctldev, dt_map->map,
60 dt_map->num_maps);
61 kfree(dt_map);
62 }
63
64 of_node_put(p->dev->of_node);
65}
66
67static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
68 struct pinctrl_dev *pctldev,
69 struct pinctrl_map *map, unsigned num_maps)
70{
71 int i;
72 struct pinctrl_dt_map *dt_map;
73
74 /* Initialize common mapping table entry fields */
75 for (i = 0; i < num_maps; i++) {
76 map[i].dev_name = dev_name(p->dev);
77 map[i].name = statename;
78 if (pctldev)
79 map[i].ctrl_dev_name = dev_name(pctldev->dev);
80 }
81
82 /* Remember the converted mapping table entries */
83 dt_map = kzalloc(sizeof(*dt_map), GFP_KERNEL);
84 if (!dt_map) {
85 dev_err(p->dev, "failed to alloc struct pinctrl_dt_map\n");
86 dt_free_map(pctldev, map, num_maps);
87 return -ENOMEM;
88 }
89
90 dt_map->pctldev = pctldev;
91 dt_map->map = map;
92 dt_map->num_maps = num_maps;
93 list_add_tail(&dt_map->node, &p->dt_maps);
94
95 return pinctrl_register_map(map, num_maps, false, true);
96}
97
98static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
99{
100 struct pinctrl_dev *pctldev;
101
102 list_for_each_entry(pctldev, &pinctrldev_list, node)
103 if (pctldev->dev->of_node == np)
104 return pctldev;
105
106 return NULL;
107}
108
109static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
110 struct device_node *np_config)
111{
112 struct device_node *np_pctldev;
113 struct pinctrl_dev *pctldev;
114 struct pinctrl_ops *ops;
115 int ret;
116 struct pinctrl_map *map;
117 unsigned num_maps;
118
119 /* Find the pin controller containing np_config */
120 np_pctldev = of_node_get(np_config);
121 for (;;) {
122 np_pctldev = of_get_next_parent(np_pctldev);
123 if (!np_pctldev || of_node_is_root(np_pctldev)) {
124 dev_err(p->dev, "could not find pctldev for node %s\n",
125 np_config->full_name);
126 of_node_put(np_pctldev);
127 /* FIXME: This should trigger deferrered probe */
128 return -ENODEV;
129 }
130 pctldev = find_pinctrl_by_of_node(np_pctldev);
131 if (pctldev)
132 break;
133 }
134 of_node_put(np_pctldev);
135
136 /*
137 * Call pinctrl driver to parse device tree node, and
138 * generate mapping table entries
139 */
140 ops = pctldev->desc->pctlops;
141 if (!ops->dt_node_to_map) {
142 dev_err(p->dev, "pctldev %s doesn't support DT\n",
143 dev_name(pctldev->dev));
144 return -ENODEV;
145 }
146 ret = ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);
147 if (ret < 0)
148 return ret;
149
150 /* Stash the mapping table chunk away for later use */
151 return dt_remember_or_free_map(p, statename, pctldev, map, num_maps);
152}
153
154static int dt_remember_dummy_state(struct pinctrl *p, const char *statename)
155{
156 struct pinctrl_map *map;
157
158 map = kzalloc(sizeof(*map), GFP_KERNEL);
159 if (!map) {
160 dev_err(p->dev, "failed to alloc struct pinctrl_map\n");
161 return -ENOMEM;
162 }
163
164 /* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
165 map->type = PIN_MAP_TYPE_DUMMY_STATE;
166
167 return dt_remember_or_free_map(p, statename, NULL, map, 1);
168}
169
170int pinctrl_dt_to_map(struct pinctrl *p)
171{
172 struct device_node *np = p->dev->of_node;
173 int state, ret;
174 char *propname;
175 struct property *prop;
176 const char *statename;
177 const __be32 *list;
178 int size, config;
179 phandle phandle;
180 struct device_node *np_config;
181
182 /* CONFIG_OF enabled, p->dev not instantiated from DT */
183 if (!np) {
184 dev_dbg(p->dev, "no of_node; not parsing pinctrl DT\n");
185 return 0;
186 }
187
188 /* We may store pointers to property names within the node */
189 of_node_get(np);
190
191 /* For each defined state ID */
192 for (state = 0; ; state++) {
193 /* Retrieve the pinctrl-* property */
194 propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
195 prop = of_find_property(np, propname, &size);
196 kfree(propname);
197 if (!prop)
198 break;
199 list = prop->value;
200 size /= sizeof(*list);
201
202 /* Determine whether pinctrl-names property names the state */
203 ret = of_property_read_string_index(np, "pinctrl-names",
204 state, &statename);
205 /*
206 * If not, statename is just the integer state ID. But rather
207 * than dynamically allocate it and have to free it later,
208 * just point part way into the property name for the string.
209 */
210 if (ret < 0) {
211 /* strlen("pinctrl-") == 8 */
212 statename = prop->name + 8;
213 }
214
215 /* For every referenced pin configuration node in it */
216 for (config = 0; config < size; config++) {
217 phandle = be32_to_cpup(list++);
218
219 /* Look up the pin configuration node */
220 np_config = of_find_node_by_phandle(phandle);
221 if (!np_config) {
222 dev_err(p->dev,
223 "prop %s index %i invalid phandle\n",
224 prop->name, config);
225 ret = -EINVAL;
226 goto err;
227 }
228
229 /* Parse the node */
230 ret = dt_to_map_one_config(p, statename, np_config);
231 of_node_put(np_config);
232 if (ret < 0)
233 goto err;
234 }
235
236 /* No entries in DT? Generate a dummy state table entry */
237 if (!size) {
238 ret = dt_remember_dummy_state(p, statename);
239 if (ret < 0)
240 goto err;
241 }
242 }
243
244 return 0;
245
246err:
247 pinctrl_dt_free_maps(p);
248 return ret;
249}
diff --git a/drivers/pinctrl/devicetree.h b/drivers/pinctrl/devicetree.h
new file mode 100644
index 000000000000..760bc4960f58
--- /dev/null
+++ b/drivers/pinctrl/devicetree.h
@@ -0,0 +1,35 @@
1/*
2 * Internal interface to pinctrl device tree integration
3 *
4 * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef CONFIG_OF
20
21void pinctrl_dt_free_maps(struct pinctrl *p);
22int pinctrl_dt_to_map(struct pinctrl *p);
23
24#else
25
26static inline int pinctrl_dt_to_map(struct pinctrl *p)
27{
28 return 0;
29}
30
31static inline void pinctrl_dt_free_maps(struct pinctrl *p)
32{
33}
34
35#endif