Root/
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 | */ |
33 | struct pinctrl_dt_map { |
34 | struct list_head node; |
35 | struct pinctrl_dev *pctldev; |
36 | struct pinctrl_map *map; |
37 | unsigned num_maps; |
38 | }; |
39 | |
40 | static 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 | |
52 | void 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 | |
67 | static 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 | |
98 | static 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 | |
109 | static 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_info(p->dev, "could not find pctldev for node %s, deferring probe\n", |
125 | np_config->full_name); |
126 | of_node_put(np_pctldev); |
127 | /* OK let's just assume this will appear later then */ |
128 | return -EPROBE_DEFER; |
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 | |
154 | static 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 | |
170 | int 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 | |
246 | err: |
247 | pinctrl_dt_free_maps(p); |
248 | return ret; |
249 | } |
250 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9