1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // |
3 | // Copyright 2012 Freescale Semiconductor, Inc. |
4 | |
5 | #include <linux/err.h> |
6 | #include <linux/init.h> |
7 | #include <linux/io.h> |
8 | #include <linux/of.h> |
9 | #include <linux/of_address.h> |
10 | #include <linux/platform_device.h> |
11 | #include <linux/seq_file.h> |
12 | #include <linux/slab.h> |
13 | |
14 | #include <linux/pinctrl/machine.h> |
15 | #include <linux/pinctrl/pinconf.h> |
16 | #include <linux/pinctrl/pinctrl.h> |
17 | #include <linux/pinctrl/pinmux.h> |
18 | |
19 | #include "../core.h" |
20 | #include "pinctrl-mxs.h" |
21 | |
22 | #define SUFFIX_LEN 4 |
23 | |
24 | struct mxs_pinctrl_data { |
25 | struct device *dev; |
26 | struct pinctrl_dev *pctl; |
27 | void __iomem *base; |
28 | struct mxs_pinctrl_soc_data *soc; |
29 | }; |
30 | |
31 | static int mxs_get_groups_count(struct pinctrl_dev *pctldev) |
32 | { |
33 | struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); |
34 | |
35 | return d->soc->ngroups; |
36 | } |
37 | |
38 | static const char *mxs_get_group_name(struct pinctrl_dev *pctldev, |
39 | unsigned group) |
40 | { |
41 | struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); |
42 | |
43 | return d->soc->groups[group].name; |
44 | } |
45 | |
46 | static int mxs_get_group_pins(struct pinctrl_dev *pctldev, unsigned group, |
47 | const unsigned **pins, unsigned *num_pins) |
48 | { |
49 | struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); |
50 | |
51 | *pins = d->soc->groups[group].pins; |
52 | *num_pins = d->soc->groups[group].npins; |
53 | |
54 | return 0; |
55 | } |
56 | |
57 | static void mxs_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, |
58 | unsigned offset) |
59 | { |
60 | seq_printf(m: s, fmt: " %s" , dev_name(dev: pctldev->dev)); |
61 | } |
62 | |
63 | static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, |
64 | struct device_node *np, |
65 | struct pinctrl_map **map, unsigned *num_maps) |
66 | { |
67 | struct pinctrl_map *new_map; |
68 | char *group = NULL; |
69 | unsigned new_num = 1; |
70 | unsigned long config = 0; |
71 | unsigned long *pconfig; |
72 | int length = strlen(np->name) + SUFFIX_LEN; |
73 | bool purecfg = false; |
74 | u32 val, reg; |
75 | int ret, i = 0; |
76 | |
77 | /* Check for pin config node which has no 'reg' property */ |
78 | if (of_property_read_u32(np, propname: "reg" , out_value: ®)) |
79 | purecfg = true; |
80 | |
81 | ret = of_property_read_u32(np, propname: "fsl,drive-strength" , out_value: &val); |
82 | if (!ret) |
83 | config = val | MA_PRESENT; |
84 | ret = of_property_read_u32(np, propname: "fsl,voltage" , out_value: &val); |
85 | if (!ret) |
86 | config |= val << VOL_SHIFT | VOL_PRESENT; |
87 | ret = of_property_read_u32(np, propname: "fsl,pull-up" , out_value: &val); |
88 | if (!ret) |
89 | config |= val << PULL_SHIFT | PULL_PRESENT; |
90 | |
91 | /* Check for group node which has both mux and config settings */ |
92 | if (!purecfg && config) |
93 | new_num = 2; |
94 | |
95 | new_map = kcalloc(n: new_num, size: sizeof(*new_map), GFP_KERNEL); |
96 | if (!new_map) |
97 | return -ENOMEM; |
98 | |
99 | if (!purecfg) { |
100 | new_map[i].type = PIN_MAP_TYPE_MUX_GROUP; |
101 | new_map[i].data.mux.function = np->name; |
102 | |
103 | /* Compose group name */ |
104 | group = kzalloc(size: length, GFP_KERNEL); |
105 | if (!group) { |
106 | ret = -ENOMEM; |
107 | goto free; |
108 | } |
109 | snprintf(buf: group, size: length, fmt: "%s.%d" , np->name, reg); |
110 | new_map[i].data.mux.group = group; |
111 | i++; |
112 | } |
113 | |
114 | if (config) { |
115 | pconfig = kmemdup(p: &config, size: sizeof(config), GFP_KERNEL); |
116 | if (!pconfig) { |
117 | ret = -ENOMEM; |
118 | goto free_group; |
119 | } |
120 | |
121 | new_map[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; |
122 | new_map[i].data.configs.group_or_pin = purecfg ? np->name : |
123 | group; |
124 | new_map[i].data.configs.configs = pconfig; |
125 | new_map[i].data.configs.num_configs = 1; |
126 | } |
127 | |
128 | *map = new_map; |
129 | *num_maps = new_num; |
130 | |
131 | return 0; |
132 | |
133 | free_group: |
134 | if (!purecfg) |
135 | kfree(objp: group); |
136 | free: |
137 | kfree(objp: new_map); |
138 | return ret; |
139 | } |
140 | |
141 | static void mxs_dt_free_map(struct pinctrl_dev *pctldev, |
142 | struct pinctrl_map *map, unsigned num_maps) |
143 | { |
144 | u32 i; |
145 | |
146 | for (i = 0; i < num_maps; i++) { |
147 | if (map[i].type == PIN_MAP_TYPE_MUX_GROUP) |
148 | kfree(objp: map[i].data.mux.group); |
149 | if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) |
150 | kfree(objp: map[i].data.configs.configs); |
151 | } |
152 | |
153 | kfree(objp: map); |
154 | } |
155 | |
156 | static const struct pinctrl_ops mxs_pinctrl_ops = { |
157 | .get_groups_count = mxs_get_groups_count, |
158 | .get_group_name = mxs_get_group_name, |
159 | .get_group_pins = mxs_get_group_pins, |
160 | .pin_dbg_show = mxs_pin_dbg_show, |
161 | .dt_node_to_map = mxs_dt_node_to_map, |
162 | .dt_free_map = mxs_dt_free_map, |
163 | }; |
164 | |
165 | static int mxs_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) |
166 | { |
167 | struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); |
168 | |
169 | return d->soc->nfunctions; |
170 | } |
171 | |
172 | static const char *mxs_pinctrl_get_func_name(struct pinctrl_dev *pctldev, |
173 | unsigned function) |
174 | { |
175 | struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); |
176 | |
177 | return d->soc->functions[function].name; |
178 | } |
179 | |
180 | static int mxs_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, |
181 | unsigned group, |
182 | const char * const **groups, |
183 | unsigned * const num_groups) |
184 | { |
185 | struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); |
186 | |
187 | *groups = d->soc->functions[group].groups; |
188 | *num_groups = d->soc->functions[group].ngroups; |
189 | |
190 | return 0; |
191 | } |
192 | |
193 | static void mxs_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg) |
194 | { |
195 | u32 tmp; |
196 | |
197 | tmp = readl(addr: reg); |
198 | tmp &= ~(mask << shift); |
199 | tmp |= value << shift; |
200 | writel(val: tmp, addr: reg); |
201 | } |
202 | |
203 | static int mxs_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector, |
204 | unsigned group) |
205 | { |
206 | struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); |
207 | struct mxs_group *g = &d->soc->groups[group]; |
208 | void __iomem *reg; |
209 | u8 bank, shift; |
210 | u16 pin; |
211 | u32 i; |
212 | |
213 | for (i = 0; i < g->npins; i++) { |
214 | bank = PINID_TO_BANK(g->pins[i]); |
215 | pin = PINID_TO_PIN(g->pins[i]); |
216 | reg = d->base + d->soc->regs->muxsel; |
217 | reg += bank * 0x20 + pin / 16 * 0x10; |
218 | shift = pin % 16 * 2; |
219 | |
220 | mxs_pinctrl_rmwl(value: g->muxsel[i], mask: 0x3, shift, reg); |
221 | } |
222 | |
223 | return 0; |
224 | } |
225 | |
226 | static const struct pinmux_ops mxs_pinmux_ops = { |
227 | .get_functions_count = mxs_pinctrl_get_funcs_count, |
228 | .get_function_name = mxs_pinctrl_get_func_name, |
229 | .get_function_groups = mxs_pinctrl_get_func_groups, |
230 | .set_mux = mxs_pinctrl_set_mux, |
231 | }; |
232 | |
233 | static int mxs_pinconf_get(struct pinctrl_dev *pctldev, |
234 | unsigned pin, unsigned long *config) |
235 | { |
236 | return -ENOTSUPP; |
237 | } |
238 | |
239 | static int mxs_pinconf_set(struct pinctrl_dev *pctldev, |
240 | unsigned pin, unsigned long *configs, |
241 | unsigned num_configs) |
242 | { |
243 | return -ENOTSUPP; |
244 | } |
245 | |
246 | static int mxs_pinconf_group_get(struct pinctrl_dev *pctldev, |
247 | unsigned group, unsigned long *config) |
248 | { |
249 | struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); |
250 | |
251 | *config = d->soc->groups[group].config; |
252 | |
253 | return 0; |
254 | } |
255 | |
256 | static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev, |
257 | unsigned group, unsigned long *configs, |
258 | unsigned num_configs) |
259 | { |
260 | struct mxs_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev); |
261 | struct mxs_group *g = &d->soc->groups[group]; |
262 | void __iomem *reg; |
263 | u8 ma, vol, pull, bank, shift; |
264 | u16 pin; |
265 | u32 i; |
266 | int n; |
267 | unsigned long config; |
268 | |
269 | for (n = 0; n < num_configs; n++) { |
270 | config = configs[n]; |
271 | |
272 | ma = PIN_CONFIG_TO_MA(config); |
273 | vol = PIN_CONFIG_TO_VOL(config); |
274 | pull = PIN_CONFIG_TO_PULL(config); |
275 | |
276 | for (i = 0; i < g->npins; i++) { |
277 | bank = PINID_TO_BANK(g->pins[i]); |
278 | pin = PINID_TO_PIN(g->pins[i]); |
279 | |
280 | /* drive */ |
281 | reg = d->base + d->soc->regs->drive; |
282 | reg += bank * 0x40 + pin / 8 * 0x10; |
283 | |
284 | /* mA */ |
285 | if (config & MA_PRESENT) { |
286 | shift = pin % 8 * 4; |
287 | mxs_pinctrl_rmwl(value: ma, mask: 0x3, shift, reg); |
288 | } |
289 | |
290 | /* vol */ |
291 | if (config & VOL_PRESENT) { |
292 | shift = pin % 8 * 4 + 2; |
293 | if (vol) |
294 | writel(val: 1 << shift, addr: reg + SET); |
295 | else |
296 | writel(val: 1 << shift, addr: reg + CLR); |
297 | } |
298 | |
299 | /* pull */ |
300 | if (config & PULL_PRESENT) { |
301 | reg = d->base + d->soc->regs->pull; |
302 | reg += bank * 0x10; |
303 | shift = pin; |
304 | if (pull) |
305 | writel(val: 1 << shift, addr: reg + SET); |
306 | else |
307 | writel(val: 1 << shift, addr: reg + CLR); |
308 | } |
309 | } |
310 | |
311 | /* cache the config value for mxs_pinconf_group_get() */ |
312 | g->config = config; |
313 | |
314 | } /* for each config */ |
315 | |
316 | return 0; |
317 | } |
318 | |
319 | static void mxs_pinconf_dbg_show(struct pinctrl_dev *pctldev, |
320 | struct seq_file *s, unsigned pin) |
321 | { |
322 | /* Not support */ |
323 | } |
324 | |
325 | static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, |
326 | struct seq_file *s, unsigned group) |
327 | { |
328 | unsigned long config; |
329 | |
330 | if (!mxs_pinconf_group_get(pctldev, group, config: &config)) |
331 | seq_printf(m: s, fmt: "0x%lx" , config); |
332 | } |
333 | |
334 | static const struct pinconf_ops mxs_pinconf_ops = { |
335 | .pin_config_get = mxs_pinconf_get, |
336 | .pin_config_set = mxs_pinconf_set, |
337 | .pin_config_group_get = mxs_pinconf_group_get, |
338 | .pin_config_group_set = mxs_pinconf_group_set, |
339 | .pin_config_dbg_show = mxs_pinconf_dbg_show, |
340 | .pin_config_group_dbg_show = mxs_pinconf_group_dbg_show, |
341 | }; |
342 | |
343 | static struct pinctrl_desc mxs_pinctrl_desc = { |
344 | .pctlops = &mxs_pinctrl_ops, |
345 | .pmxops = &mxs_pinmux_ops, |
346 | .confops = &mxs_pinconf_ops, |
347 | .owner = THIS_MODULE, |
348 | }; |
349 | |
350 | static int mxs_pinctrl_parse_group(struct platform_device *pdev, |
351 | struct device_node *np, int idx, |
352 | const char **out_name) |
353 | { |
354 | struct mxs_pinctrl_data *d = platform_get_drvdata(pdev); |
355 | struct mxs_group *g = &d->soc->groups[idx]; |
356 | struct property *prop; |
357 | const char *propname = "fsl,pinmux-ids" ; |
358 | char *group; |
359 | int length = strlen(np->name) + SUFFIX_LEN; |
360 | u32 val, i; |
361 | |
362 | group = devm_kzalloc(dev: &pdev->dev, size: length, GFP_KERNEL); |
363 | if (!group) |
364 | return -ENOMEM; |
365 | if (of_property_read_u32(np, propname: "reg" , out_value: &val)) |
366 | snprintf(buf: group, size: length, fmt: "%s" , np->name); |
367 | else |
368 | snprintf(buf: group, size: length, fmt: "%s.%d" , np->name, val); |
369 | g->name = group; |
370 | |
371 | prop = of_find_property(np, name: propname, lenp: &length); |
372 | if (!prop) |
373 | return -EINVAL; |
374 | g->npins = length / sizeof(u32); |
375 | |
376 | g->pins = devm_kcalloc(dev: &pdev->dev, n: g->npins, size: sizeof(*g->pins), |
377 | GFP_KERNEL); |
378 | if (!g->pins) |
379 | return -ENOMEM; |
380 | |
381 | g->muxsel = devm_kcalloc(dev: &pdev->dev, n: g->npins, size: sizeof(*g->muxsel), |
382 | GFP_KERNEL); |
383 | if (!g->muxsel) |
384 | return -ENOMEM; |
385 | |
386 | of_property_read_u32_array(np, propname, out_values: g->pins, sz: g->npins); |
387 | for (i = 0; i < g->npins; i++) { |
388 | g->muxsel[i] = MUXID_TO_MUXSEL(g->pins[i]); |
389 | g->pins[i] = MUXID_TO_PINID(g->pins[i]); |
390 | } |
391 | |
392 | if (out_name) |
393 | *out_name = g->name; |
394 | |
395 | return 0; |
396 | } |
397 | |
398 | static bool is_mxs_gpio(struct device_node *child) |
399 | { |
400 | return of_device_is_compatible(device: child, "fsl,imx23-gpio" ) || |
401 | of_device_is_compatible(device: child, "fsl,imx28-gpio" ); |
402 | } |
403 | |
404 | static int mxs_pinctrl_probe_dt(struct platform_device *pdev, |
405 | struct mxs_pinctrl_data *d) |
406 | { |
407 | struct mxs_pinctrl_soc_data *soc = d->soc; |
408 | struct device_node *np = pdev->dev.of_node; |
409 | struct device_node *child; |
410 | struct mxs_function *f; |
411 | const char *fn, *fnull = "" ; |
412 | int i = 0, idxf = 0, idxg = 0; |
413 | int ret; |
414 | u32 val; |
415 | |
416 | child = of_get_next_child(node: np, NULL); |
417 | if (!child) { |
418 | dev_err(&pdev->dev, "no group is defined\n" ); |
419 | return -ENOENT; |
420 | } |
421 | |
422 | /* Count total functions and groups */ |
423 | fn = fnull; |
424 | for_each_child_of_node(np, child) { |
425 | if (is_mxs_gpio(child)) |
426 | continue; |
427 | soc->ngroups++; |
428 | /* Skip pure pinconf node */ |
429 | if (of_property_read_u32(np: child, propname: "reg" , out_value: &val)) |
430 | continue; |
431 | if (strcmp(fn, child->name)) { |
432 | fn = child->name; |
433 | soc->nfunctions++; |
434 | } |
435 | } |
436 | |
437 | soc->functions = devm_kcalloc(dev: &pdev->dev, |
438 | n: soc->nfunctions, |
439 | size: sizeof(*soc->functions), |
440 | GFP_KERNEL); |
441 | if (!soc->functions) |
442 | return -ENOMEM; |
443 | |
444 | soc->groups = devm_kcalloc(dev: &pdev->dev, |
445 | n: soc->ngroups, size: sizeof(*soc->groups), |
446 | GFP_KERNEL); |
447 | if (!soc->groups) |
448 | return -ENOMEM; |
449 | |
450 | /* Count groups for each function */ |
451 | fn = fnull; |
452 | f = &soc->functions[idxf]; |
453 | for_each_child_of_node(np, child) { |
454 | if (is_mxs_gpio(child)) |
455 | continue; |
456 | if (of_property_read_u32(np: child, propname: "reg" , out_value: &val)) |
457 | continue; |
458 | if (strcmp(fn, child->name)) { |
459 | struct device_node *child2; |
460 | |
461 | /* |
462 | * This reference is dropped by |
463 | * of_get_next_child(np, * child) |
464 | */ |
465 | of_node_get(node: child); |
466 | |
467 | /* |
468 | * The logic parsing the functions from dt currently |
469 | * doesn't handle if functions with the same name are |
470 | * not grouped together. Only the first contiguous |
471 | * cluster is usable for each function name. This is a |
472 | * bug that is not trivial to fix, but at least warn |
473 | * about it. |
474 | */ |
475 | for (child2 = of_get_next_child(node: np, prev: child); |
476 | child2 != NULL; |
477 | child2 = of_get_next_child(node: np, prev: child2)) { |
478 | if (!strcmp(child2->name, fn)) |
479 | dev_warn(&pdev->dev, |
480 | "function nodes must be grouped by name (failed for: %s)" , |
481 | fn); |
482 | } |
483 | |
484 | f = &soc->functions[idxf++]; |
485 | f->name = fn = child->name; |
486 | } |
487 | f->ngroups++; |
488 | } |
489 | |
490 | /* Get groups for each function */ |
491 | idxf = 0; |
492 | fn = fnull; |
493 | for_each_child_of_node(np, child) { |
494 | if (is_mxs_gpio(child)) |
495 | continue; |
496 | if (of_property_read_u32(np: child, propname: "reg" , out_value: &val)) { |
497 | ret = mxs_pinctrl_parse_group(pdev, np: child, |
498 | idx: idxg++, NULL); |
499 | if (ret) { |
500 | of_node_put(node: child); |
501 | return ret; |
502 | } |
503 | continue; |
504 | } |
505 | |
506 | if (strcmp(fn, child->name)) { |
507 | f = &soc->functions[idxf++]; |
508 | f->groups = devm_kcalloc(dev: &pdev->dev, |
509 | n: f->ngroups, |
510 | size: sizeof(*f->groups), |
511 | GFP_KERNEL); |
512 | if (!f->groups) { |
513 | of_node_put(node: child); |
514 | return -ENOMEM; |
515 | } |
516 | fn = child->name; |
517 | i = 0; |
518 | } |
519 | ret = mxs_pinctrl_parse_group(pdev, np: child, idx: idxg++, |
520 | out_name: &f->groups[i++]); |
521 | if (ret) { |
522 | of_node_put(node: child); |
523 | return ret; |
524 | } |
525 | } |
526 | |
527 | return 0; |
528 | } |
529 | |
530 | int mxs_pinctrl_probe(struct platform_device *pdev, |
531 | struct mxs_pinctrl_soc_data *soc) |
532 | { |
533 | struct device_node *np = pdev->dev.of_node; |
534 | struct mxs_pinctrl_data *d; |
535 | int ret; |
536 | |
537 | d = devm_kzalloc(dev: &pdev->dev, size: sizeof(*d), GFP_KERNEL); |
538 | if (!d) |
539 | return -ENOMEM; |
540 | |
541 | d->dev = &pdev->dev; |
542 | d->soc = soc; |
543 | |
544 | d->base = of_iomap(node: np, index: 0); |
545 | if (!d->base) |
546 | return -EADDRNOTAVAIL; |
547 | |
548 | mxs_pinctrl_desc.pins = d->soc->pins; |
549 | mxs_pinctrl_desc.npins = d->soc->npins; |
550 | mxs_pinctrl_desc.name = dev_name(dev: &pdev->dev); |
551 | |
552 | platform_set_drvdata(pdev, data: d); |
553 | |
554 | ret = mxs_pinctrl_probe_dt(pdev, d); |
555 | if (ret) { |
556 | dev_err(&pdev->dev, "dt probe failed: %d\n" , ret); |
557 | goto err; |
558 | } |
559 | |
560 | d->pctl = pinctrl_register(pctldesc: &mxs_pinctrl_desc, dev: &pdev->dev, driver_data: d); |
561 | if (IS_ERR(ptr: d->pctl)) { |
562 | dev_err(&pdev->dev, "Couldn't register MXS pinctrl driver\n" ); |
563 | ret = PTR_ERR(ptr: d->pctl); |
564 | goto err; |
565 | } |
566 | |
567 | return 0; |
568 | |
569 | err: |
570 | iounmap(addr: d->base); |
571 | return ret; |
572 | } |
573 | |