diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-imx1-core.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-imx1-core.c | 653 |
1 files changed, 653 insertions, 0 deletions
diff --git a/drivers/pinctrl/pinctrl-imx1-core.c b/drivers/pinctrl/pinctrl-imx1-core.c new file mode 100644 index 000000000000..f77914ac081a --- /dev/null +++ b/drivers/pinctrl/pinctrl-imx1-core.c | |||
@@ -0,0 +1,653 @@ | |||
1 | /* | ||
2 | * Core driver for the imx pin controller in imx1/21/27 | ||
3 | * | ||
4 | * Copyright (C) 2013 Pengutronix | ||
5 | * Author: Markus Pargmann <mpa@pengutronix.de> | ||
6 | * | ||
7 | * Based on pinctrl-imx.c: | ||
8 | * Author: Dong Aisheng <dong.aisheng@linaro.org> | ||
9 | * Copyright (C) 2012 Freescale Semiconductor, Inc. | ||
10 | * Copyright (C) 2012 Linaro Ltd. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/bitops.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/of.h> | ||
24 | #include <linux/of_device.h> | ||
25 | #include <linux/pinctrl/machine.h> | ||
26 | #include <linux/pinctrl/pinconf.h> | ||
27 | #include <linux/pinctrl/pinctrl.h> | ||
28 | #include <linux/pinctrl/pinmux.h> | ||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #include "core.h" | ||
32 | #include "pinctrl-imx1.h" | ||
33 | |||
34 | struct imx1_pinctrl { | ||
35 | struct device *dev; | ||
36 | struct pinctrl_dev *pctl; | ||
37 | void __iomem *base; | ||
38 | const struct imx1_pinctrl_soc_info *info; | ||
39 | }; | ||
40 | |||
41 | /* | ||
42 | * MX1 register offsets | ||
43 | */ | ||
44 | |||
45 | #define MX1_DDIR 0x00 | ||
46 | #define MX1_OCR 0x04 | ||
47 | #define MX1_ICONFA 0x0c | ||
48 | #define MX1_ICONFB 0x10 | ||
49 | #define MX1_GIUS 0x20 | ||
50 | #define MX1_GPR 0x38 | ||
51 | #define MX1_PUEN 0x40 | ||
52 | |||
53 | #define MX1_PORT_STRIDE 0x100 | ||
54 | |||
55 | |||
56 | /* | ||
57 | * MUX_ID format defines | ||
58 | */ | ||
59 | #define MX1_MUX_FUNCTION(val) (BIT(0) & val) | ||
60 | #define MX1_MUX_GPIO(val) ((BIT(1) & val) >> 1) | ||
61 | #define MX1_MUX_DIR(val) ((BIT(2) & val) >> 2) | ||
62 | #define MX1_MUX_OCONF(val) (((BIT(4) | BIT(5)) & val) >> 4) | ||
63 | #define MX1_MUX_ICONFA(val) (((BIT(8) | BIT(9)) & val) >> 8) | ||
64 | #define MX1_MUX_ICONFB(val) (((BIT(10) | BIT(11)) & val) >> 10) | ||
65 | |||
66 | |||
67 | /* | ||
68 | * IMX1 IOMUXC manages the pins based on ports. Each port has 32 pins. IOMUX | ||
69 | * control register are seperated into function, output configuration, input | ||
70 | * configuration A, input configuration B, GPIO in use and data direction. | ||
71 | * | ||
72 | * Those controls that are represented by 1 bit have a direct mapping between | ||
73 | * bit position and pin id. If they are represented by 2 bit, the lower 16 pins | ||
74 | * are in the first register and the upper 16 pins in the second (next) | ||
75 | * register. pin_id is stored in bit (pin_id%16)*2 and the bit above. | ||
76 | */ | ||
77 | |||
78 | /* | ||
79 | * Calculates the register offset from a pin_id | ||
80 | */ | ||
81 | static void __iomem *imx1_mem(struct imx1_pinctrl *ipctl, unsigned int pin_id) | ||
82 | { | ||
83 | unsigned int port = pin_id / 32; | ||
84 | return ipctl->base + port * MX1_PORT_STRIDE; | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * Write to a register with 2 bits per pin. The function will automatically | ||
89 | * use the next register if the pin is managed in the second register. | ||
90 | */ | ||
91 | static void imx1_write_2bit(struct imx1_pinctrl *ipctl, unsigned int pin_id, | ||
92 | u32 value, u32 reg_offset) | ||
93 | { | ||
94 | void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset; | ||
95 | int offset = (pin_id % 16) * 2; /* offset, regardless of register used */ | ||
96 | int mask = ~(0x3 << offset); /* Mask for 2 bits at offset */ | ||
97 | u32 old_val; | ||
98 | u32 new_val; | ||
99 | |||
100 | dev_dbg(ipctl->dev, "write: register 0x%p offset %d value 0x%x\n", | ||
101 | reg, offset, value); | ||
102 | |||
103 | /* Use the next register if the pin's port pin number is >=16 */ | ||
104 | if (pin_id % 32 >= 16) | ||
105 | reg += 0x04; | ||
106 | |||
107 | /* Get current state of pins */ | ||
108 | old_val = readl(reg); | ||
109 | old_val &= mask; | ||
110 | |||
111 | new_val = value & 0x3; /* Make sure value is really 2 bit */ | ||
112 | new_val <<= offset; | ||
113 | new_val |= old_val;/* Set new state for pin_id */ | ||
114 | |||
115 | writel(new_val, reg); | ||
116 | } | ||
117 | |||
118 | static void imx1_write_bit(struct imx1_pinctrl *ipctl, unsigned int pin_id, | ||
119 | u32 value, u32 reg_offset) | ||
120 | { | ||
121 | void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset; | ||
122 | int offset = pin_id % 32; | ||
123 | int mask = ~BIT_MASK(offset); | ||
124 | u32 old_val; | ||
125 | u32 new_val; | ||
126 | |||
127 | /* Get current state of pins */ | ||
128 | old_val = readl(reg); | ||
129 | old_val &= mask; | ||
130 | |||
131 | new_val = value & 0x1; /* Make sure value is really 1 bit */ | ||
132 | new_val <<= offset; | ||
133 | new_val |= old_val;/* Set new state for pin_id */ | ||
134 | |||
135 | writel(new_val, reg); | ||
136 | } | ||
137 | |||
138 | static int imx1_read_2bit(struct imx1_pinctrl *ipctl, unsigned int pin_id, | ||
139 | u32 reg_offset) | ||
140 | { | ||
141 | void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset; | ||
142 | int offset = pin_id % 16; | ||
143 | |||
144 | /* Use the next register if the pin's port pin number is >=16 */ | ||
145 | if (pin_id % 32 >= 16) | ||
146 | reg += 0x04; | ||
147 | |||
148 | return (readl(reg) & (BIT(offset) | BIT(offset+1))) >> offset; | ||
149 | } | ||
150 | |||
151 | static int imx1_read_bit(struct imx1_pinctrl *ipctl, unsigned int pin_id, | ||
152 | u32 reg_offset) | ||
153 | { | ||
154 | void __iomem *reg = imx1_mem(ipctl, pin_id) + reg_offset; | ||
155 | int offset = pin_id % 32; | ||
156 | |||
157 | return !!(readl(reg) & BIT(offset)); | ||
158 | } | ||
159 | |||
160 | static const inline struct imx1_pin_group *imx1_pinctrl_find_group_by_name( | ||
161 | const struct imx1_pinctrl_soc_info *info, | ||
162 | const char *name) | ||
163 | { | ||
164 | const struct imx1_pin_group *grp = NULL; | ||
165 | int i; | ||
166 | |||
167 | for (i = 0; i < info->ngroups; i++) { | ||
168 | if (!strcmp(info->groups[i].name, name)) { | ||
169 | grp = &info->groups[i]; | ||
170 | break; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | return grp; | ||
175 | } | ||
176 | |||
177 | static int imx1_get_groups_count(struct pinctrl_dev *pctldev) | ||
178 | { | ||
179 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
180 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
181 | |||
182 | return info->ngroups; | ||
183 | } | ||
184 | |||
185 | static const char *imx1_get_group_name(struct pinctrl_dev *pctldev, | ||
186 | unsigned selector) | ||
187 | { | ||
188 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
189 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
190 | |||
191 | return info->groups[selector].name; | ||
192 | } | ||
193 | |||
194 | static int imx1_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, | ||
195 | const unsigned int **pins, | ||
196 | unsigned *npins) | ||
197 | { | ||
198 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
199 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
200 | |||
201 | if (selector >= info->ngroups) | ||
202 | return -EINVAL; | ||
203 | |||
204 | *pins = info->groups[selector].pin_ids; | ||
205 | *npins = info->groups[selector].npins; | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static void imx1_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, | ||
211 | unsigned offset) | ||
212 | { | ||
213 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
214 | |||
215 | seq_printf(s, "GPIO %d, function %d, direction %d, oconf %d, iconfa %d, iconfb %d", | ||
216 | imx1_read_bit(ipctl, offset, MX1_GIUS), | ||
217 | imx1_read_bit(ipctl, offset, MX1_GPR), | ||
218 | imx1_read_bit(ipctl, offset, MX1_DDIR), | ||
219 | imx1_read_2bit(ipctl, offset, MX1_OCR), | ||
220 | imx1_read_2bit(ipctl, offset, MX1_ICONFA), | ||
221 | imx1_read_2bit(ipctl, offset, MX1_ICONFB)); | ||
222 | } | ||
223 | |||
224 | static int imx1_dt_node_to_map(struct pinctrl_dev *pctldev, | ||
225 | struct device_node *np, | ||
226 | struct pinctrl_map **map, unsigned *num_maps) | ||
227 | { | ||
228 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
229 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
230 | const struct imx1_pin_group *grp; | ||
231 | struct pinctrl_map *new_map; | ||
232 | struct device_node *parent; | ||
233 | int map_num = 1; | ||
234 | int i, j; | ||
235 | |||
236 | /* | ||
237 | * first find the group of this node and check if we need create | ||
238 | * config maps for pins | ||
239 | */ | ||
240 | grp = imx1_pinctrl_find_group_by_name(info, np->name); | ||
241 | if (!grp) { | ||
242 | dev_err(info->dev, "unable to find group for node %s\n", | ||
243 | np->name); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | |||
247 | for (i = 0; i < grp->npins; i++) | ||
248 | map_num++; | ||
249 | |||
250 | new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL); | ||
251 | if (!new_map) | ||
252 | return -ENOMEM; | ||
253 | |||
254 | *map = new_map; | ||
255 | *num_maps = map_num; | ||
256 | |||
257 | /* create mux map */ | ||
258 | parent = of_get_parent(np); | ||
259 | if (!parent) { | ||
260 | kfree(new_map); | ||
261 | return -EINVAL; | ||
262 | } | ||
263 | new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; | ||
264 | new_map[0].data.mux.function = parent->name; | ||
265 | new_map[0].data.mux.group = np->name; | ||
266 | of_node_put(parent); | ||
267 | |||
268 | /* create config map */ | ||
269 | new_map++; | ||
270 | for (i = j = 0; i < grp->npins; i++) { | ||
271 | new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN; | ||
272 | new_map[j].data.configs.group_or_pin = | ||
273 | pin_get_name(pctldev, grp->pins[i].pin_id); | ||
274 | new_map[j].data.configs.configs = &grp->pins[i].config; | ||
275 | new_map[j].data.configs.num_configs = 1; | ||
276 | j++; | ||
277 | } | ||
278 | |||
279 | dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", | ||
280 | (*map)->data.mux.function, (*map)->data.mux.group, map_num); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static void imx1_dt_free_map(struct pinctrl_dev *pctldev, | ||
286 | struct pinctrl_map *map, unsigned num_maps) | ||
287 | { | ||
288 | kfree(map); | ||
289 | } | ||
290 | |||
291 | static const struct pinctrl_ops imx1_pctrl_ops = { | ||
292 | .get_groups_count = imx1_get_groups_count, | ||
293 | .get_group_name = imx1_get_group_name, | ||
294 | .get_group_pins = imx1_get_group_pins, | ||
295 | .pin_dbg_show = imx1_pin_dbg_show, | ||
296 | .dt_node_to_map = imx1_dt_node_to_map, | ||
297 | .dt_free_map = imx1_dt_free_map, | ||
298 | |||
299 | }; | ||
300 | |||
301 | static int imx1_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, | ||
302 | unsigned group) | ||
303 | { | ||
304 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
305 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
306 | const struct imx1_pin *pins; | ||
307 | unsigned int npins; | ||
308 | int i; | ||
309 | |||
310 | /* | ||
311 | * Configure the mux mode for each pin in the group for a specific | ||
312 | * function. | ||
313 | */ | ||
314 | pins = info->groups[group].pins; | ||
315 | npins = info->groups[group].npins; | ||
316 | |||
317 | WARN_ON(!pins || !npins); | ||
318 | |||
319 | dev_dbg(ipctl->dev, "enable function %s group %s\n", | ||
320 | info->functions[selector].name, info->groups[group].name); | ||
321 | |||
322 | for (i = 0; i < npins; i++) { | ||
323 | unsigned int mux = pins[i].mux_id; | ||
324 | unsigned int pin_id = pins[i].pin_id; | ||
325 | unsigned int afunction = MX1_MUX_FUNCTION(mux); | ||
326 | unsigned int gpio_in_use = MX1_MUX_GPIO(mux); | ||
327 | unsigned int direction = MX1_MUX_DIR(mux); | ||
328 | unsigned int gpio_oconf = MX1_MUX_OCONF(mux); | ||
329 | unsigned int gpio_iconfa = MX1_MUX_ICONFA(mux); | ||
330 | unsigned int gpio_iconfb = MX1_MUX_ICONFB(mux); | ||
331 | |||
332 | dev_dbg(pctldev->dev, "%s, pin 0x%x, function %d, gpio %d, direction %d, oconf %d, iconfa %d, iconfb %d\n", | ||
333 | __func__, pin_id, afunction, gpio_in_use, | ||
334 | direction, gpio_oconf, gpio_iconfa, | ||
335 | gpio_iconfb); | ||
336 | |||
337 | imx1_write_bit(ipctl, pin_id, gpio_in_use, MX1_GIUS); | ||
338 | imx1_write_bit(ipctl, pin_id, direction, MX1_DDIR); | ||
339 | |||
340 | if (gpio_in_use) { | ||
341 | imx1_write_2bit(ipctl, pin_id, gpio_oconf, MX1_OCR); | ||
342 | imx1_write_2bit(ipctl, pin_id, gpio_iconfa, | ||
343 | MX1_ICONFA); | ||
344 | imx1_write_2bit(ipctl, pin_id, gpio_iconfb, | ||
345 | MX1_ICONFB); | ||
346 | } else { | ||
347 | imx1_write_bit(ipctl, pin_id, afunction, MX1_GPR); | ||
348 | } | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | static int imx1_pmx_get_funcs_count(struct pinctrl_dev *pctldev) | ||
355 | { | ||
356 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
357 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
358 | |||
359 | return info->nfunctions; | ||
360 | } | ||
361 | |||
362 | static const char *imx1_pmx_get_func_name(struct pinctrl_dev *pctldev, | ||
363 | unsigned selector) | ||
364 | { | ||
365 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
366 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
367 | |||
368 | return info->functions[selector].name; | ||
369 | } | ||
370 | |||
371 | static int imx1_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, | ||
372 | const char * const **groups, | ||
373 | unsigned * const num_groups) | ||
374 | { | ||
375 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
376 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
377 | |||
378 | *groups = info->functions[selector].groups; | ||
379 | *num_groups = info->functions[selector].num_groups; | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static const struct pinmux_ops imx1_pmx_ops = { | ||
385 | .get_functions_count = imx1_pmx_get_funcs_count, | ||
386 | .get_function_name = imx1_pmx_get_func_name, | ||
387 | .get_function_groups = imx1_pmx_get_groups, | ||
388 | .enable = imx1_pmx_enable, | ||
389 | }; | ||
390 | |||
391 | static int imx1_pinconf_get(struct pinctrl_dev *pctldev, | ||
392 | unsigned pin_id, unsigned long *config) | ||
393 | { | ||
394 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
395 | |||
396 | *config = imx1_read_bit(ipctl, pin_id, MX1_PUEN); | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int imx1_pinconf_set(struct pinctrl_dev *pctldev, | ||
402 | unsigned pin_id, unsigned long *configs, | ||
403 | unsigned num_configs) | ||
404 | { | ||
405 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
406 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
407 | int i; | ||
408 | |||
409 | for (i = 0; i != num_configs; ++i) { | ||
410 | imx1_write_bit(ipctl, pin_id, configs[i] & 0x01, MX1_PUEN); | ||
411 | |||
412 | dev_dbg(ipctl->dev, "pinconf set pullup pin %s\n", | ||
413 | info->pins[pin_id].name); | ||
414 | } | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static void imx1_pinconf_dbg_show(struct pinctrl_dev *pctldev, | ||
420 | struct seq_file *s, unsigned pin_id) | ||
421 | { | ||
422 | unsigned long config; | ||
423 | |||
424 | imx1_pinconf_get(pctldev, pin_id, &config); | ||
425 | seq_printf(s, "0x%lx", config); | ||
426 | } | ||
427 | |||
428 | static void imx1_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, | ||
429 | struct seq_file *s, unsigned group) | ||
430 | { | ||
431 | struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); | ||
432 | const struct imx1_pinctrl_soc_info *info = ipctl->info; | ||
433 | struct imx1_pin_group *grp; | ||
434 | unsigned long config; | ||
435 | const char *name; | ||
436 | int i, ret; | ||
437 | |||
438 | if (group > info->ngroups) | ||
439 | return; | ||
440 | |||
441 | seq_puts(s, "\n"); | ||
442 | grp = &info->groups[group]; | ||
443 | for (i = 0; i < grp->npins; i++) { | ||
444 | name = pin_get_name(pctldev, grp->pins[i].pin_id); | ||
445 | ret = imx1_pinconf_get(pctldev, grp->pins[i].pin_id, &config); | ||
446 | if (ret) | ||
447 | return; | ||
448 | seq_printf(s, "%s: 0x%lx", name, config); | ||
449 | } | ||
450 | } | ||
451 | |||
452 | static const struct pinconf_ops imx1_pinconf_ops = { | ||
453 | .pin_config_get = imx1_pinconf_get, | ||
454 | .pin_config_set = imx1_pinconf_set, | ||
455 | .pin_config_dbg_show = imx1_pinconf_dbg_show, | ||
456 | .pin_config_group_dbg_show = imx1_pinconf_group_dbg_show, | ||
457 | }; | ||
458 | |||
459 | static struct pinctrl_desc imx1_pinctrl_desc = { | ||
460 | .pctlops = &imx1_pctrl_ops, | ||
461 | .pmxops = &imx1_pmx_ops, | ||
462 | .confops = &imx1_pinconf_ops, | ||
463 | .owner = THIS_MODULE, | ||
464 | }; | ||
465 | |||
466 | static int imx1_pinctrl_parse_groups(struct device_node *np, | ||
467 | struct imx1_pin_group *grp, | ||
468 | struct imx1_pinctrl_soc_info *info, | ||
469 | u32 index) | ||
470 | { | ||
471 | int size; | ||
472 | const __be32 *list; | ||
473 | int i; | ||
474 | |||
475 | dev_dbg(info->dev, "group(%d): %s\n", index, np->name); | ||
476 | |||
477 | /* Initialise group */ | ||
478 | grp->name = np->name; | ||
479 | |||
480 | /* | ||
481 | * the binding format is fsl,pins = <PIN MUX_ID CONFIG> | ||
482 | */ | ||
483 | list = of_get_property(np, "fsl,pins", &size); | ||
484 | /* we do not check return since it's safe node passed down */ | ||
485 | if (!size || size % 12) { | ||
486 | dev_notice(info->dev, "Not a valid fsl,pins property (%s)\n", | ||
487 | np->name); | ||
488 | return -EINVAL; | ||
489 | } | ||
490 | |||
491 | grp->npins = size / 12; | ||
492 | grp->pins = devm_kzalloc(info->dev, | ||
493 | grp->npins * sizeof(struct imx1_pin), GFP_KERNEL); | ||
494 | grp->pin_ids = devm_kzalloc(info->dev, | ||
495 | grp->npins * sizeof(unsigned int), GFP_KERNEL); | ||
496 | |||
497 | if (!grp->pins || !grp->pin_ids) | ||
498 | return -ENOMEM; | ||
499 | |||
500 | for (i = 0; i < grp->npins; i++) { | ||
501 | grp->pins[i].pin_id = be32_to_cpu(*list++); | ||
502 | grp->pins[i].mux_id = be32_to_cpu(*list++); | ||
503 | grp->pins[i].config = be32_to_cpu(*list++); | ||
504 | |||
505 | grp->pin_ids[i] = grp->pins[i].pin_id; | ||
506 | } | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static int imx1_pinctrl_parse_functions(struct device_node *np, | ||
512 | struct imx1_pinctrl_soc_info *info, | ||
513 | u32 index) | ||
514 | { | ||
515 | struct device_node *child; | ||
516 | struct imx1_pmx_func *func; | ||
517 | struct imx1_pin_group *grp; | ||
518 | int ret; | ||
519 | static u32 grp_index; | ||
520 | u32 i = 0; | ||
521 | |||
522 | dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name); | ||
523 | |||
524 | func = &info->functions[index]; | ||
525 | |||
526 | /* Initialise function */ | ||
527 | func->name = np->name; | ||
528 | func->num_groups = of_get_child_count(np); | ||
529 | if (func->num_groups <= 0) | ||
530 | return -EINVAL; | ||
531 | |||
532 | func->groups = devm_kzalloc(info->dev, | ||
533 | func->num_groups * sizeof(char *), GFP_KERNEL); | ||
534 | |||
535 | if (!func->groups) | ||
536 | return -ENOMEM; | ||
537 | |||
538 | for_each_child_of_node(np, child) { | ||
539 | func->groups[i] = child->name; | ||
540 | grp = &info->groups[grp_index++]; | ||
541 | ret = imx1_pinctrl_parse_groups(child, grp, info, i++); | ||
542 | if (ret == -ENOMEM) | ||
543 | return ret; | ||
544 | } | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static int imx1_pinctrl_parse_dt(struct platform_device *pdev, | ||
550 | struct imx1_pinctrl *pctl, struct imx1_pinctrl_soc_info *info) | ||
551 | { | ||
552 | struct device_node *np = pdev->dev.of_node; | ||
553 | struct device_node *child; | ||
554 | int ret; | ||
555 | u32 nfuncs = 0; | ||
556 | u32 ngroups = 0; | ||
557 | u32 ifunc = 0; | ||
558 | |||
559 | if (!np) | ||
560 | return -ENODEV; | ||
561 | |||
562 | for_each_child_of_node(np, child) { | ||
563 | ++nfuncs; | ||
564 | ngroups += of_get_child_count(child); | ||
565 | } | ||
566 | |||
567 | if (!nfuncs) { | ||
568 | dev_err(&pdev->dev, "No pin functions defined\n"); | ||
569 | return -EINVAL; | ||
570 | } | ||
571 | |||
572 | info->nfunctions = nfuncs; | ||
573 | info->functions = devm_kzalloc(&pdev->dev, | ||
574 | nfuncs * sizeof(struct imx1_pmx_func), GFP_KERNEL); | ||
575 | |||
576 | info->ngroups = ngroups; | ||
577 | info->groups = devm_kzalloc(&pdev->dev, | ||
578 | ngroups * sizeof(struct imx1_pin_group), GFP_KERNEL); | ||
579 | |||
580 | |||
581 | if (!info->functions || !info->groups) | ||
582 | return -ENOMEM; | ||
583 | |||
584 | for_each_child_of_node(np, child) { | ||
585 | ret = imx1_pinctrl_parse_functions(child, info, ifunc++); | ||
586 | if (ret == -ENOMEM) | ||
587 | return -ENOMEM; | ||
588 | } | ||
589 | |||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | int imx1_pinctrl_core_probe(struct platform_device *pdev, | ||
594 | struct imx1_pinctrl_soc_info *info) | ||
595 | { | ||
596 | struct imx1_pinctrl *ipctl; | ||
597 | struct resource *res; | ||
598 | struct pinctrl_desc *pctl_desc; | ||
599 | int ret; | ||
600 | |||
601 | if (!info || !info->pins || !info->npins) { | ||
602 | dev_err(&pdev->dev, "wrong pinctrl info\n"); | ||
603 | return -EINVAL; | ||
604 | } | ||
605 | info->dev = &pdev->dev; | ||
606 | |||
607 | /* Create state holders etc for this driver */ | ||
608 | ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL); | ||
609 | if (!ipctl) | ||
610 | return -ENOMEM; | ||
611 | |||
612 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
613 | if (!res) | ||
614 | return -ENOENT; | ||
615 | |||
616 | ipctl->base = devm_ioremap_nocache(&pdev->dev, res->start, | ||
617 | resource_size(res)); | ||
618 | if (!ipctl->base) | ||
619 | return -ENOMEM; | ||
620 | |||
621 | pctl_desc = &imx1_pinctrl_desc; | ||
622 | pctl_desc->name = dev_name(&pdev->dev); | ||
623 | pctl_desc->pins = info->pins; | ||
624 | pctl_desc->npins = info->npins; | ||
625 | |||
626 | ret = imx1_pinctrl_parse_dt(pdev, ipctl, info); | ||
627 | if (ret) { | ||
628 | dev_err(&pdev->dev, "fail to probe dt properties\n"); | ||
629 | return ret; | ||
630 | } | ||
631 | |||
632 | ipctl->info = info; | ||
633 | ipctl->dev = info->dev; | ||
634 | platform_set_drvdata(pdev, ipctl); | ||
635 | ipctl->pctl = pinctrl_register(pctl_desc, &pdev->dev, ipctl); | ||
636 | if (!ipctl->pctl) { | ||
637 | dev_err(&pdev->dev, "could not register IMX pinctrl driver\n"); | ||
638 | return -EINVAL; | ||
639 | } | ||
640 | |||
641 | dev_info(&pdev->dev, "initialized IMX pinctrl driver\n"); | ||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | int imx1_pinctrl_core_remove(struct platform_device *pdev) | ||
647 | { | ||
648 | struct imx1_pinctrl *ipctl = platform_get_drvdata(pdev); | ||
649 | |||
650 | pinctrl_unregister(ipctl->pctl); | ||
651 | |||
652 | return 0; | ||
653 | } | ||