1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Marvell MVEBU pinctrl core driver |
4 | * |
5 | * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> |
6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> |
7 | */ |
8 | |
9 | #include <linux/err.h> |
10 | #include <linux/gpio/driver.h> |
11 | #include <linux/io.h> |
12 | #include <linux/mfd/syscon.h> |
13 | #include <linux/of.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/regmap.h> |
16 | #include <linux/seq_file.h> |
17 | #include <linux/slab.h> |
18 | |
19 | #include <linux/pinctrl/machine.h> |
20 | #include <linux/pinctrl/pinconf.h> |
21 | #include <linux/pinctrl/pinctrl.h> |
22 | #include <linux/pinctrl/pinmux.h> |
23 | |
24 | #include "pinctrl-mvebu.h" |
25 | |
26 | #define MPPS_PER_REG 8 |
27 | #define MPP_BITS 4 |
28 | #define MPP_MASK 0xf |
29 | |
30 | struct mvebu_pinctrl_function { |
31 | const char *name; |
32 | const char **groups; |
33 | unsigned num_groups; |
34 | }; |
35 | |
36 | struct mvebu_pinctrl_group { |
37 | const char *name; |
38 | const struct mvebu_mpp_ctrl *ctrl; |
39 | struct mvebu_mpp_ctrl_data *data; |
40 | struct mvebu_mpp_ctrl_setting *settings; |
41 | unsigned num_settings; |
42 | unsigned gid; |
43 | unsigned *pins; |
44 | unsigned npins; |
45 | }; |
46 | |
47 | struct mvebu_pinctrl { |
48 | struct device *dev; |
49 | struct pinctrl_dev *pctldev; |
50 | struct pinctrl_desc desc; |
51 | struct mvebu_pinctrl_group *groups; |
52 | unsigned num_groups; |
53 | struct mvebu_pinctrl_function *functions; |
54 | unsigned num_functions; |
55 | u8 variant; |
56 | }; |
57 | |
58 | int mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, |
59 | unsigned int pid, unsigned long *config) |
60 | { |
61 | unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; |
62 | unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; |
63 | |
64 | *config = (readl(addr: data->base + off) >> shift) & MVEBU_MPP_MASK; |
65 | |
66 | return 0; |
67 | } |
68 | |
69 | int mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, |
70 | unsigned int pid, unsigned long config) |
71 | { |
72 | unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; |
73 | unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; |
74 | unsigned long reg; |
75 | |
76 | reg = readl(addr: data->base + off) & ~(MVEBU_MPP_MASK << shift); |
77 | writel(val: reg | (config << shift), addr: data->base + off); |
78 | |
79 | return 0; |
80 | } |
81 | |
82 | static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_pid( |
83 | struct mvebu_pinctrl *pctl, unsigned pid) |
84 | { |
85 | unsigned n; |
86 | for (n = 0; n < pctl->num_groups; n++) { |
87 | if (pid >= pctl->groups[n].pins[0] && |
88 | pid < pctl->groups[n].pins[0] + |
89 | pctl->groups[n].npins) |
90 | return &pctl->groups[n]; |
91 | } |
92 | return NULL; |
93 | } |
94 | |
95 | static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_name( |
96 | struct mvebu_pinctrl *pctl, const char *name) |
97 | { |
98 | unsigned n; |
99 | |
100 | for (n = 0; n < pctl->num_groups; n++) { |
101 | if (strcmp(name, pctl->groups[n].name) == 0) |
102 | return &pctl->groups[n]; |
103 | } |
104 | |
105 | return NULL; |
106 | } |
107 | |
108 | static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_val( |
109 | struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp, |
110 | unsigned long config) |
111 | { |
112 | unsigned n; |
113 | |
114 | for (n = 0; n < grp->num_settings; n++) { |
115 | if (config == grp->settings[n].val) { |
116 | if (!pctl->variant || (pctl->variant & |
117 | grp->settings[n].variant)) |
118 | return &grp->settings[n]; |
119 | } |
120 | } |
121 | |
122 | return NULL; |
123 | } |
124 | |
125 | static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_name( |
126 | struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp, |
127 | const char *name) |
128 | { |
129 | unsigned n; |
130 | |
131 | for (n = 0; n < grp->num_settings; n++) { |
132 | if (strcmp(name, grp->settings[n].name) == 0) { |
133 | if (!pctl->variant || (pctl->variant & |
134 | grp->settings[n].variant)) |
135 | return &grp->settings[n]; |
136 | } |
137 | } |
138 | |
139 | return NULL; |
140 | } |
141 | |
142 | static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_gpio_setting( |
143 | struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp) |
144 | { |
145 | unsigned n; |
146 | |
147 | for (n = 0; n < grp->num_settings; n++) { |
148 | if (grp->settings[n].flags & |
149 | (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) { |
150 | if (!pctl->variant || (pctl->variant & |
151 | grp->settings[n].variant)) |
152 | return &grp->settings[n]; |
153 | } |
154 | } |
155 | |
156 | return NULL; |
157 | } |
158 | |
159 | static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name( |
160 | struct mvebu_pinctrl *pctl, const char *name) |
161 | { |
162 | unsigned n; |
163 | |
164 | for (n = 0; n < pctl->num_functions; n++) { |
165 | if (strcmp(name, pctl->functions[n].name) == 0) |
166 | return &pctl->functions[n]; |
167 | } |
168 | |
169 | return NULL; |
170 | } |
171 | |
172 | static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev, |
173 | unsigned gid, unsigned long *config) |
174 | { |
175 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
176 | struct mvebu_pinctrl_group *grp = &pctl->groups[gid]; |
177 | |
178 | if (!grp->ctrl) |
179 | return -EINVAL; |
180 | |
181 | return grp->ctrl->mpp_get(grp->data, grp->pins[0], config); |
182 | } |
183 | |
184 | static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev, |
185 | unsigned gid, unsigned long *configs, |
186 | unsigned num_configs) |
187 | { |
188 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
189 | struct mvebu_pinctrl_group *grp = &pctl->groups[gid]; |
190 | int i, ret; |
191 | |
192 | if (!grp->ctrl) |
193 | return -EINVAL; |
194 | |
195 | for (i = 0; i < num_configs; i++) { |
196 | ret = grp->ctrl->mpp_set(grp->data, grp->pins[0], configs[i]); |
197 | if (ret) |
198 | return ret; |
199 | } /* for each config */ |
200 | |
201 | return 0; |
202 | } |
203 | |
204 | static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, |
205 | struct seq_file *s, unsigned gid) |
206 | { |
207 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
208 | struct mvebu_pinctrl_group *grp = &pctl->groups[gid]; |
209 | struct mvebu_mpp_ctrl_setting *curr; |
210 | unsigned long config; |
211 | unsigned n; |
212 | |
213 | if (mvebu_pinconf_group_get(pctldev, gid, config: &config)) |
214 | return; |
215 | |
216 | curr = mvebu_pinctrl_find_setting_by_val(pctl, grp, config); |
217 | |
218 | if (curr) { |
219 | seq_printf(m: s, fmt: "current: %s" , curr->name); |
220 | if (curr->subname) |
221 | seq_printf(m: s, fmt: "(%s)" , curr->subname); |
222 | if (curr->flags & (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) { |
223 | seq_putc(m: s, c: '('); |
224 | if (curr->flags & MVEBU_SETTING_GPI) |
225 | seq_putc(m: s, c: 'i'); |
226 | if (curr->flags & MVEBU_SETTING_GPO) |
227 | seq_putc(m: s, c: 'o'); |
228 | seq_putc(m: s, c: ')'); |
229 | } |
230 | } else { |
231 | seq_puts(m: s, s: "current: UNKNOWN" ); |
232 | } |
233 | |
234 | if (grp->num_settings > 1) { |
235 | seq_puts(m: s, s: ", available = [" ); |
236 | for (n = 0; n < grp->num_settings; n++) { |
237 | if (curr == &grp->settings[n]) |
238 | continue; |
239 | |
240 | /* skip unsupported settings for this variant */ |
241 | if (pctl->variant && |
242 | !(pctl->variant & grp->settings[n].variant)) |
243 | continue; |
244 | |
245 | seq_printf(m: s, fmt: " %s" , grp->settings[n].name); |
246 | if (grp->settings[n].subname) |
247 | seq_printf(m: s, fmt: "(%s)" , grp->settings[n].subname); |
248 | if (grp->settings[n].flags & |
249 | (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) { |
250 | seq_putc(m: s, c: '('); |
251 | if (grp->settings[n].flags & MVEBU_SETTING_GPI) |
252 | seq_putc(m: s, c: 'i'); |
253 | if (grp->settings[n].flags & MVEBU_SETTING_GPO) |
254 | seq_putc(m: s, c: 'o'); |
255 | seq_putc(m: s, c: ')'); |
256 | } |
257 | } |
258 | seq_puts(m: s, s: " ]" ); |
259 | } |
260 | } |
261 | |
262 | static const struct pinconf_ops mvebu_pinconf_ops = { |
263 | .pin_config_group_get = mvebu_pinconf_group_get, |
264 | .pin_config_group_set = mvebu_pinconf_group_set, |
265 | .pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show, |
266 | }; |
267 | |
268 | static int mvebu_pinmux_get_funcs_count(struct pinctrl_dev *pctldev) |
269 | { |
270 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
271 | |
272 | return pctl->num_functions; |
273 | } |
274 | |
275 | static const char *mvebu_pinmux_get_func_name(struct pinctrl_dev *pctldev, |
276 | unsigned fid) |
277 | { |
278 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
279 | |
280 | return pctl->functions[fid].name; |
281 | } |
282 | |
283 | static int mvebu_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned fid, |
284 | const char * const **groups, |
285 | unsigned * const num_groups) |
286 | { |
287 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
288 | |
289 | *groups = pctl->functions[fid].groups; |
290 | *num_groups = pctl->functions[fid].num_groups; |
291 | return 0; |
292 | } |
293 | |
294 | static int mvebu_pinmux_set(struct pinctrl_dev *pctldev, unsigned fid, |
295 | unsigned gid) |
296 | { |
297 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
298 | struct mvebu_pinctrl_function *func = &pctl->functions[fid]; |
299 | struct mvebu_pinctrl_group *grp = &pctl->groups[gid]; |
300 | struct mvebu_mpp_ctrl_setting *setting; |
301 | int ret; |
302 | unsigned long config; |
303 | |
304 | setting = mvebu_pinctrl_find_setting_by_name(pctl, grp, |
305 | name: func->name); |
306 | if (!setting) { |
307 | dev_err(pctl->dev, |
308 | "unable to find setting %s in group %s\n" , |
309 | func->name, func->groups[gid]); |
310 | return -EINVAL; |
311 | } |
312 | |
313 | config = setting->val; |
314 | ret = mvebu_pinconf_group_set(pctldev, gid: grp->gid, configs: &config, num_configs: 1); |
315 | if (ret) { |
316 | dev_err(pctl->dev, "cannot set group %s to %s\n" , |
317 | func->groups[gid], func->name); |
318 | return ret; |
319 | } |
320 | |
321 | return 0; |
322 | } |
323 | |
324 | static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, |
325 | struct pinctrl_gpio_range *range, unsigned offset) |
326 | { |
327 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
328 | struct mvebu_pinctrl_group *grp; |
329 | struct mvebu_mpp_ctrl_setting *setting; |
330 | unsigned long config; |
331 | |
332 | grp = mvebu_pinctrl_find_group_by_pid(pctl, pid: offset); |
333 | if (!grp) |
334 | return -EINVAL; |
335 | |
336 | if (grp->ctrl->mpp_gpio_req) |
337 | return grp->ctrl->mpp_gpio_req(grp->data, offset); |
338 | |
339 | setting = mvebu_pinctrl_find_gpio_setting(pctl, grp); |
340 | if (!setting) |
341 | return -ENOTSUPP; |
342 | |
343 | config = setting->val; |
344 | |
345 | return mvebu_pinconf_group_set(pctldev, gid: grp->gid, configs: &config, num_configs: 1); |
346 | } |
347 | |
348 | static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, |
349 | struct pinctrl_gpio_range *range, unsigned offset, bool input) |
350 | { |
351 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
352 | struct mvebu_pinctrl_group *grp; |
353 | struct mvebu_mpp_ctrl_setting *setting; |
354 | |
355 | grp = mvebu_pinctrl_find_group_by_pid(pctl, pid: offset); |
356 | if (!grp) |
357 | return -EINVAL; |
358 | |
359 | if (grp->ctrl->mpp_gpio_dir) |
360 | return grp->ctrl->mpp_gpio_dir(grp->data, offset, input); |
361 | |
362 | setting = mvebu_pinctrl_find_gpio_setting(pctl, grp); |
363 | if (!setting) |
364 | return -ENOTSUPP; |
365 | |
366 | if ((input && (setting->flags & MVEBU_SETTING_GPI)) || |
367 | (!input && (setting->flags & MVEBU_SETTING_GPO))) |
368 | return 0; |
369 | |
370 | return -ENOTSUPP; |
371 | } |
372 | |
373 | static const struct pinmux_ops mvebu_pinmux_ops = { |
374 | .get_functions_count = mvebu_pinmux_get_funcs_count, |
375 | .get_function_name = mvebu_pinmux_get_func_name, |
376 | .get_function_groups = mvebu_pinmux_get_groups, |
377 | .gpio_request_enable = mvebu_pinmux_gpio_request_enable, |
378 | .gpio_set_direction = mvebu_pinmux_gpio_set_direction, |
379 | .set_mux = mvebu_pinmux_set, |
380 | }; |
381 | |
382 | static int mvebu_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) |
383 | { |
384 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
385 | return pctl->num_groups; |
386 | } |
387 | |
388 | static const char *mvebu_pinctrl_get_group_name(struct pinctrl_dev *pctldev, |
389 | unsigned gid) |
390 | { |
391 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
392 | return pctl->groups[gid].name; |
393 | } |
394 | |
395 | static int mvebu_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, |
396 | unsigned gid, const unsigned **pins, |
397 | unsigned *num_pins) |
398 | { |
399 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
400 | *pins = pctl->groups[gid].pins; |
401 | *num_pins = pctl->groups[gid].npins; |
402 | return 0; |
403 | } |
404 | |
405 | static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, |
406 | struct device_node *np, |
407 | struct pinctrl_map **map, |
408 | unsigned *num_maps) |
409 | { |
410 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); |
411 | struct property *prop; |
412 | const char *function; |
413 | const char *group; |
414 | int ret, nmaps, n; |
415 | |
416 | *map = NULL; |
417 | *num_maps = 0; |
418 | |
419 | ret = of_property_read_string(np, propname: "marvell,function" , out_string: &function); |
420 | if (ret) { |
421 | dev_err(pctl->dev, |
422 | "missing marvell,function in node %pOFn\n" , np); |
423 | return 0; |
424 | } |
425 | |
426 | nmaps = of_property_count_strings(np, propname: "marvell,pins" ); |
427 | if (nmaps < 0) { |
428 | dev_err(pctl->dev, |
429 | "missing marvell,pins in node %pOFn\n" , np); |
430 | return 0; |
431 | } |
432 | |
433 | *map = kmalloc_array(n: nmaps, size: sizeof(**map), GFP_KERNEL); |
434 | if (!*map) |
435 | return -ENOMEM; |
436 | |
437 | n = 0; |
438 | of_property_for_each_string(np, "marvell,pins" , prop, group) { |
439 | struct mvebu_pinctrl_group *grp = |
440 | mvebu_pinctrl_find_group_by_name(pctl, name: group); |
441 | |
442 | if (!grp) { |
443 | dev_err(pctl->dev, "unknown pin %s" , group); |
444 | continue; |
445 | } |
446 | |
447 | if (!mvebu_pinctrl_find_setting_by_name(pctl, grp, name: function)) { |
448 | dev_err(pctl->dev, "unsupported function %s on pin %s" , |
449 | function, group); |
450 | continue; |
451 | } |
452 | |
453 | (*map)[n].type = PIN_MAP_TYPE_MUX_GROUP; |
454 | (*map)[n].data.mux.group = group; |
455 | (*map)[n].data.mux.function = function; |
456 | n++; |
457 | } |
458 | |
459 | *num_maps = nmaps; |
460 | |
461 | return 0; |
462 | } |
463 | |
464 | static void mvebu_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, |
465 | struct pinctrl_map *map, unsigned num_maps) |
466 | { |
467 | kfree(objp: map); |
468 | } |
469 | |
470 | static const struct pinctrl_ops mvebu_pinctrl_ops = { |
471 | .get_groups_count = mvebu_pinctrl_get_groups_count, |
472 | .get_group_name = mvebu_pinctrl_get_group_name, |
473 | .get_group_pins = mvebu_pinctrl_get_group_pins, |
474 | .dt_node_to_map = mvebu_pinctrl_dt_node_to_map, |
475 | .dt_free_map = mvebu_pinctrl_dt_free_map, |
476 | }; |
477 | |
478 | static int _add_function(struct mvebu_pinctrl_function *funcs, int *funcsize, |
479 | const char *name) |
480 | { |
481 | if (*funcsize <= 0) |
482 | return -EOVERFLOW; |
483 | |
484 | while (funcs->num_groups) { |
485 | /* function already there */ |
486 | if (strcmp(funcs->name, name) == 0) { |
487 | funcs->num_groups++; |
488 | return -EEXIST; |
489 | } |
490 | funcs++; |
491 | } |
492 | |
493 | /* append new unique function */ |
494 | funcs->name = name; |
495 | funcs->num_groups = 1; |
496 | (*funcsize)--; |
497 | |
498 | return 0; |
499 | } |
500 | |
501 | static int mvebu_pinctrl_build_functions(struct platform_device *pdev, |
502 | struct mvebu_pinctrl *pctl) |
503 | { |
504 | struct mvebu_pinctrl_function *funcs; |
505 | int num = 0, funcsize = pctl->desc.npins; |
506 | int n, s; |
507 | |
508 | /* we allocate functions for number of pins and hope |
509 | * there are fewer unique functions than pins available */ |
510 | funcs = devm_kcalloc(dev: &pdev->dev, |
511 | n: funcsize, size: sizeof(struct mvebu_pinctrl_function), |
512 | GFP_KERNEL); |
513 | if (!funcs) |
514 | return -ENOMEM; |
515 | |
516 | for (n = 0; n < pctl->num_groups; n++) { |
517 | struct mvebu_pinctrl_group *grp = &pctl->groups[n]; |
518 | for (s = 0; s < grp->num_settings; s++) { |
519 | int ret; |
520 | |
521 | /* skip unsupported settings on this variant */ |
522 | if (pctl->variant && |
523 | !(pctl->variant & grp->settings[s].variant)) |
524 | continue; |
525 | |
526 | /* check for unique functions and count groups */ |
527 | ret = _add_function(funcs, funcsize: &funcsize, |
528 | name: grp->settings[s].name); |
529 | if (ret == -EOVERFLOW) |
530 | dev_err(&pdev->dev, |
531 | "More functions than pins(%d)\n" , |
532 | pctl->desc.npins); |
533 | if (ret < 0) |
534 | continue; |
535 | |
536 | num++; |
537 | } |
538 | } |
539 | |
540 | pctl->num_functions = num; |
541 | pctl->functions = funcs; |
542 | |
543 | for (n = 0; n < pctl->num_groups; n++) { |
544 | struct mvebu_pinctrl_group *grp = &pctl->groups[n]; |
545 | for (s = 0; s < grp->num_settings; s++) { |
546 | struct mvebu_pinctrl_function *f; |
547 | const char **groups; |
548 | |
549 | /* skip unsupported settings on this variant */ |
550 | if (pctl->variant && |
551 | !(pctl->variant & grp->settings[s].variant)) |
552 | continue; |
553 | |
554 | f = mvebu_pinctrl_find_function_by_name(pctl, |
555 | name: grp->settings[s].name); |
556 | |
557 | /* allocate group name array if not done already */ |
558 | if (!f->groups) { |
559 | f->groups = devm_kcalloc(dev: &pdev->dev, |
560 | n: f->num_groups, |
561 | size: sizeof(char *), |
562 | GFP_KERNEL); |
563 | if (!f->groups) |
564 | return -ENOMEM; |
565 | } |
566 | |
567 | /* find next free group name and assign current name */ |
568 | groups = f->groups; |
569 | while (*groups) |
570 | groups++; |
571 | *groups = grp->name; |
572 | } |
573 | } |
574 | |
575 | return 0; |
576 | } |
577 | |
578 | int mvebu_pinctrl_probe(struct platform_device *pdev) |
579 | { |
580 | struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(dev: &pdev->dev); |
581 | struct mvebu_pinctrl *pctl; |
582 | struct pinctrl_pin_desc *pdesc; |
583 | unsigned gid, n, k; |
584 | unsigned size, noname = 0; |
585 | char *noname_buf; |
586 | void *p; |
587 | int ret; |
588 | |
589 | if (!soc || !soc->controls || !soc->modes) { |
590 | dev_err(&pdev->dev, "wrong pinctrl soc info\n" ); |
591 | return -EINVAL; |
592 | } |
593 | |
594 | pctl = devm_kzalloc(dev: &pdev->dev, size: sizeof(struct mvebu_pinctrl), |
595 | GFP_KERNEL); |
596 | if (!pctl) |
597 | return -ENOMEM; |
598 | |
599 | pctl->desc.name = dev_name(dev: &pdev->dev); |
600 | pctl->desc.owner = THIS_MODULE; |
601 | pctl->desc.pctlops = &mvebu_pinctrl_ops; |
602 | pctl->desc.pmxops = &mvebu_pinmux_ops; |
603 | pctl->desc.confops = &mvebu_pinconf_ops; |
604 | pctl->variant = soc->variant; |
605 | pctl->dev = &pdev->dev; |
606 | platform_set_drvdata(pdev, data: pctl); |
607 | |
608 | /* count controls and create names for mvebu generic |
609 | register controls; also does sanity checks */ |
610 | pctl->num_groups = 0; |
611 | pctl->desc.npins = 0; |
612 | for (n = 0; n < soc->ncontrols; n++) { |
613 | const struct mvebu_mpp_ctrl *ctrl = &soc->controls[n]; |
614 | |
615 | pctl->desc.npins += ctrl->npins; |
616 | /* initialize control's pins[] array */ |
617 | for (k = 0; k < ctrl->npins; k++) |
618 | ctrl->pins[k] = ctrl->pid + k; |
619 | |
620 | /* |
621 | * We allow to pass controls with NULL name that we treat |
622 | * as a range of one-pin groups with generic mvebu register |
623 | * controls. |
624 | */ |
625 | if (!ctrl->name) { |
626 | pctl->num_groups += ctrl->npins; |
627 | noname += ctrl->npins; |
628 | } else { |
629 | pctl->num_groups += 1; |
630 | } |
631 | } |
632 | |
633 | pdesc = devm_kcalloc(dev: &pdev->dev, |
634 | n: pctl->desc.npins, |
635 | size: sizeof(struct pinctrl_pin_desc), |
636 | GFP_KERNEL); |
637 | if (!pdesc) |
638 | return -ENOMEM; |
639 | |
640 | for (n = 0; n < pctl->desc.npins; n++) |
641 | pdesc[n].number = n; |
642 | pctl->desc.pins = pdesc; |
643 | |
644 | /* |
645 | * allocate groups and name buffers for unnamed groups. |
646 | */ |
647 | size = pctl->num_groups * sizeof(*pctl->groups) + noname * 8; |
648 | p = devm_kzalloc(dev: &pdev->dev, size, GFP_KERNEL); |
649 | if (!p) |
650 | return -ENOMEM; |
651 | |
652 | pctl->groups = p; |
653 | noname_buf = p + pctl->num_groups * sizeof(*pctl->groups); |
654 | |
655 | /* assign mpp controls to groups */ |
656 | gid = 0; |
657 | for (n = 0; n < soc->ncontrols; n++) { |
658 | const struct mvebu_mpp_ctrl *ctrl = &soc->controls[n]; |
659 | struct mvebu_mpp_ctrl_data *data = soc->control_data ? |
660 | &soc->control_data[n] : NULL; |
661 | |
662 | pctl->groups[gid].gid = gid; |
663 | pctl->groups[gid].ctrl = ctrl; |
664 | pctl->groups[gid].data = data; |
665 | pctl->groups[gid].name = ctrl->name; |
666 | pctl->groups[gid].pins = ctrl->pins; |
667 | pctl->groups[gid].npins = ctrl->npins; |
668 | |
669 | /* |
670 | * We treat unnamed controls as a range of one-pin groups |
671 | * with generic mvebu register controls. Use one group for |
672 | * each in this range and assign a default group name. |
673 | */ |
674 | if (!ctrl->name) { |
675 | pctl->groups[gid].name = noname_buf; |
676 | pctl->groups[gid].npins = 1; |
677 | sprintf(buf: noname_buf, fmt: "mpp%d" , ctrl->pid+0); |
678 | noname_buf += 8; |
679 | |
680 | for (k = 1; k < ctrl->npins; k++) { |
681 | gid++; |
682 | pctl->groups[gid].gid = gid; |
683 | pctl->groups[gid].ctrl = ctrl; |
684 | pctl->groups[gid].data = data; |
685 | pctl->groups[gid].name = noname_buf; |
686 | pctl->groups[gid].pins = &ctrl->pins[k]; |
687 | pctl->groups[gid].npins = 1; |
688 | sprintf(buf: noname_buf, fmt: "mpp%d" , ctrl->pid+k); |
689 | noname_buf += 8; |
690 | } |
691 | } |
692 | gid++; |
693 | } |
694 | |
695 | /* assign mpp modes to groups */ |
696 | for (n = 0; n < soc->nmodes; n++) { |
697 | struct mvebu_mpp_mode *mode = &soc->modes[n]; |
698 | struct mvebu_mpp_ctrl_setting *set = &mode->settings[0]; |
699 | struct mvebu_pinctrl_group *grp; |
700 | unsigned num_settings; |
701 | unsigned supp_settings; |
702 | |
703 | for (num_settings = 0, supp_settings = 0; ; set++) { |
704 | if (!set->name) |
705 | break; |
706 | |
707 | num_settings++; |
708 | |
709 | /* skip unsupported settings for this variant */ |
710 | if (pctl->variant && !(pctl->variant & set->variant)) |
711 | continue; |
712 | |
713 | supp_settings++; |
714 | |
715 | /* find gpio/gpo/gpi settings */ |
716 | if (strcmp(set->name, "gpio" ) == 0) |
717 | set->flags = MVEBU_SETTING_GPI | |
718 | MVEBU_SETTING_GPO; |
719 | else if (strcmp(set->name, "gpo" ) == 0) |
720 | set->flags = MVEBU_SETTING_GPO; |
721 | else if (strcmp(set->name, "gpi" ) == 0) |
722 | set->flags = MVEBU_SETTING_GPI; |
723 | } |
724 | |
725 | /* skip modes with no settings for this variant */ |
726 | if (!supp_settings) |
727 | continue; |
728 | |
729 | grp = mvebu_pinctrl_find_group_by_pid(pctl, pid: mode->pid); |
730 | if (!grp) { |
731 | dev_warn(&pdev->dev, "unknown pinctrl group %d\n" , |
732 | mode->pid); |
733 | continue; |
734 | } |
735 | |
736 | grp->settings = mode->settings; |
737 | grp->num_settings = num_settings; |
738 | } |
739 | |
740 | ret = mvebu_pinctrl_build_functions(pdev, pctl); |
741 | if (ret) { |
742 | dev_err(&pdev->dev, "unable to build functions\n" ); |
743 | return ret; |
744 | } |
745 | |
746 | pctl->pctldev = devm_pinctrl_register(dev: &pdev->dev, pctldesc: &pctl->desc, driver_data: pctl); |
747 | if (IS_ERR(ptr: pctl->pctldev)) { |
748 | dev_err(&pdev->dev, "unable to register pinctrl driver\n" ); |
749 | return PTR_ERR(ptr: pctl->pctldev); |
750 | } |
751 | |
752 | dev_info(&pdev->dev, "registered pinctrl driver\n" ); |
753 | |
754 | /* register gpio ranges */ |
755 | for (n = 0; n < soc->ngpioranges; n++) |
756 | pinctrl_add_gpio_range(pctldev: pctl->pctldev, range: &soc->gpioranges[n]); |
757 | |
758 | return 0; |
759 | } |
760 | |
761 | /* |
762 | * mvebu_pinctrl_simple_mmio_probe - probe a simple mmio pinctrl |
763 | * @pdev: platform device (with platform data already attached) |
764 | * |
765 | * Initialise a simple (single base address) mmio pinctrl driver, |
766 | * assigning the MMIO base address to all mvebu mpp ctrl instances. |
767 | */ |
768 | int mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev) |
769 | { |
770 | struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(dev: &pdev->dev); |
771 | struct mvebu_mpp_ctrl_data *mpp_data; |
772 | void __iomem *base; |
773 | int i; |
774 | |
775 | base = devm_platform_ioremap_resource(pdev, index: 0); |
776 | if (IS_ERR(ptr: base)) |
777 | return PTR_ERR(ptr: base); |
778 | |
779 | mpp_data = devm_kcalloc(dev: &pdev->dev, n: soc->ncontrols, size: sizeof(*mpp_data), |
780 | GFP_KERNEL); |
781 | if (!mpp_data) |
782 | return -ENOMEM; |
783 | |
784 | for (i = 0; i < soc->ncontrols; i++) |
785 | mpp_data[i].base = base; |
786 | |
787 | soc->control_data = mpp_data; |
788 | |
789 | return mvebu_pinctrl_probe(pdev); |
790 | } |
791 | |
792 | int mvebu_regmap_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, |
793 | unsigned int pid, unsigned long *config) |
794 | { |
795 | unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; |
796 | unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; |
797 | unsigned int val; |
798 | int err; |
799 | |
800 | err = regmap_read(map: data->regmap.map, reg: data->regmap.offset + off, val: &val); |
801 | if (err) |
802 | return err; |
803 | |
804 | *config = (val >> shift) & MVEBU_MPP_MASK; |
805 | |
806 | return 0; |
807 | } |
808 | |
809 | int mvebu_regmap_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, |
810 | unsigned int pid, unsigned long config) |
811 | { |
812 | unsigned off = (pid / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; |
813 | unsigned shift = (pid % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS; |
814 | |
815 | return regmap_update_bits(map: data->regmap.map, reg: data->regmap.offset + off, |
816 | MVEBU_MPP_MASK << shift, val: config << shift); |
817 | } |
818 | |
819 | int mvebu_pinctrl_simple_regmap_probe(struct platform_device *pdev, |
820 | struct device *syscon_dev, u32 offset) |
821 | { |
822 | struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(dev: &pdev->dev); |
823 | struct mvebu_mpp_ctrl_data *mpp_data; |
824 | struct regmap *regmap; |
825 | int i; |
826 | |
827 | regmap = syscon_node_to_regmap(np: syscon_dev->of_node); |
828 | if (IS_ERR(ptr: regmap)) |
829 | return PTR_ERR(ptr: regmap); |
830 | |
831 | mpp_data = devm_kcalloc(dev: &pdev->dev, n: soc->ncontrols, size: sizeof(*mpp_data), |
832 | GFP_KERNEL); |
833 | if (!mpp_data) |
834 | return -ENOMEM; |
835 | |
836 | for (i = 0; i < soc->ncontrols; i++) { |
837 | mpp_data[i].regmap.map = regmap; |
838 | mpp_data[i].regmap.offset = offset; |
839 | } |
840 | |
841 | soc->control_data = mpp_data; |
842 | |
843 | return mvebu_pinctrl_probe(pdev); |
844 | } |
845 | |