1 /*
2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15 #include <linux/export.h>
16 #include <linux/mfd/syscon.h>
17 #include <linux/pinctrl/pinconf.h>
18 #include <linux/pinctrl/pinconf-generic.h>
19 #include <linux/pinctrl/pinctrl.h>
20 #include <linux/pinctrl/pinmux.h>
21 #include <linux/platform_device.h>
22 #include <linux/regmap.h>
23
24 #include "../core.h"
25 #include "../pinctrl-utils.h"
26 #include "pinctrl-uniphier.h"
27
28 struct uniphier_pinctrl_priv {
29 struct pinctrl_dev *pctldev;
30 struct regmap *regmap;
31 struct uniphier_pinctrl_socdata *socdata;
32 };
33
uniphier_pctl_get_groups_count(struct pinctrl_dev * pctldev)34 static int uniphier_pctl_get_groups_count(struct pinctrl_dev *pctldev)
35 {
36 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
37
38 return priv->socdata->groups_count;
39 }
40
uniphier_pctl_get_group_name(struct pinctrl_dev * pctldev,unsigned selector)41 static const char *uniphier_pctl_get_group_name(struct pinctrl_dev *pctldev,
42 unsigned selector)
43 {
44 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
45
46 return priv->socdata->groups[selector].name;
47 }
48
uniphier_pctl_get_group_pins(struct pinctrl_dev * pctldev,unsigned selector,const unsigned ** pins,unsigned * num_pins)49 static int uniphier_pctl_get_group_pins(struct pinctrl_dev *pctldev,
50 unsigned selector,
51 const unsigned **pins,
52 unsigned *num_pins)
53 {
54 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
55
56 *pins = priv->socdata->groups[selector].pins;
57 *num_pins = priv->socdata->groups[selector].num_pins;
58
59 return 0;
60 }
61
62 #ifdef CONFIG_DEBUG_FS
uniphier_pctl_pin_dbg_show(struct pinctrl_dev * pctldev,struct seq_file * s,unsigned offset)63 static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
64 struct seq_file *s, unsigned offset)
65 {
66 const struct pinctrl_pin_desc *pin = &pctldev->desc->pins[offset];
67 const char *pull_dir, *drv_str;
68
69 switch (uniphier_pin_get_pull_dir(pin->drv_data)) {
70 case UNIPHIER_PIN_PULL_UP:
71 pull_dir = "UP";
72 break;
73 case UNIPHIER_PIN_PULL_DOWN:
74 pull_dir = "DOWN";
75 break;
76 case UNIPHIER_PIN_PULL_UP_FIXED:
77 pull_dir = "UP(FIXED)";
78 break;
79 case UNIPHIER_PIN_PULL_DOWN_FIXED:
80 pull_dir = "DOWN(FIXED)";
81 break;
82 case UNIPHIER_PIN_PULL_NONE:
83 pull_dir = "NONE";
84 break;
85 default:
86 BUG();
87 }
88
89 switch (uniphier_pin_get_drv_str(pin->drv_data)) {
90 case UNIPHIER_PIN_DRV_4_8:
91 drv_str = "4/8(mA)";
92 break;
93 case UNIPHIER_PIN_DRV_8_12_16_20:
94 drv_str = "8/12/16/20(mA)";
95 break;
96 case UNIPHIER_PIN_DRV_FIXED_4:
97 drv_str = "4(mA)";
98 break;
99 case UNIPHIER_PIN_DRV_FIXED_5:
100 drv_str = "5(mA)";
101 break;
102 case UNIPHIER_PIN_DRV_FIXED_8:
103 drv_str = "8(mA)";
104 break;
105 case UNIPHIER_PIN_DRV_NONE:
106 drv_str = "NONE";
107 break;
108 default:
109 BUG();
110 }
111
112 seq_printf(s, " PULL_DIR=%s DRV_STR=%s", pull_dir, drv_str);
113 }
114 #endif
115
116 static const struct pinctrl_ops uniphier_pctlops = {
117 .get_groups_count = uniphier_pctl_get_groups_count,
118 .get_group_name = uniphier_pctl_get_group_name,
119 .get_group_pins = uniphier_pctl_get_group_pins,
120 #ifdef CONFIG_DEBUG_FS
121 .pin_dbg_show = uniphier_pctl_pin_dbg_show,
122 #endif
123 .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
124 .dt_free_map = pinctrl_utils_dt_free_map,
125 };
126
uniphier_conf_pin_bias_get(struct pinctrl_dev * pctldev,const struct pinctrl_pin_desc * pin,enum pin_config_param param)127 static int uniphier_conf_pin_bias_get(struct pinctrl_dev *pctldev,
128 const struct pinctrl_pin_desc *pin,
129 enum pin_config_param param)
130 {
131 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
132 enum uniphier_pin_pull_dir pull_dir =
133 uniphier_pin_get_pull_dir(pin->drv_data);
134 unsigned int pupdctrl, reg, shift, val;
135 unsigned int expected = 1;
136 int ret;
137
138 switch (param) {
139 case PIN_CONFIG_BIAS_DISABLE:
140 if (pull_dir == UNIPHIER_PIN_PULL_NONE)
141 return 0;
142 if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
143 pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)
144 return -EINVAL;
145 expected = 0;
146 break;
147 case PIN_CONFIG_BIAS_PULL_UP:
148 if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED)
149 return 0;
150 if (pull_dir != UNIPHIER_PIN_PULL_UP)
151 return -EINVAL;
152 break;
153 case PIN_CONFIG_BIAS_PULL_DOWN:
154 if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED)
155 return 0;
156 if (pull_dir != UNIPHIER_PIN_PULL_DOWN)
157 return -EINVAL;
158 break;
159 default:
160 BUG();
161 }
162
163 pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
164
165 reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
166 shift = pupdctrl % 32;
167
168 ret = regmap_read(priv->regmap, reg, &val);
169 if (ret)
170 return ret;
171
172 val = (val >> shift) & 1;
173
174 return (val == expected) ? 0 : -EINVAL;
175 }
176
uniphier_conf_pin_drive_get(struct pinctrl_dev * pctldev,const struct pinctrl_pin_desc * pin,u16 * strength)177 static int uniphier_conf_pin_drive_get(struct pinctrl_dev *pctldev,
178 const struct pinctrl_pin_desc *pin,
179 u16 *strength)
180 {
181 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
182 enum uniphier_pin_drv_str drv_str =
183 uniphier_pin_get_drv_str(pin->drv_data);
184 const unsigned int strength_4_8[] = {4, 8};
185 const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20};
186 const unsigned int *supported_strength;
187 unsigned int drvctrl, reg, shift, mask, width, val;
188 int ret;
189
190 switch (drv_str) {
191 case UNIPHIER_PIN_DRV_4_8:
192 supported_strength = strength_4_8;
193 width = 1;
194 break;
195 case UNIPHIER_PIN_DRV_8_12_16_20:
196 supported_strength = strength_8_12_16_20;
197 width = 2;
198 break;
199 case UNIPHIER_PIN_DRV_FIXED_4:
200 *strength = 4;
201 return 0;
202 case UNIPHIER_PIN_DRV_FIXED_5:
203 *strength = 5;
204 return 0;
205 case UNIPHIER_PIN_DRV_FIXED_8:
206 *strength = 8;
207 return 0;
208 default:
209 /* drive strength control is not supported for this pin */
210 return -EINVAL;
211 }
212
213 drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
214 drvctrl *= width;
215
216 reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
217 UNIPHIER_PINCTRL_DRVCTRL_BASE;
218
219 reg += drvctrl / 32 * 4;
220 shift = drvctrl % 32;
221 mask = (1U << width) - 1;
222
223 ret = regmap_read(priv->regmap, reg, &val);
224 if (ret)
225 return ret;
226
227 *strength = supported_strength[(val >> shift) & mask];
228
229 return 0;
230 }
231
uniphier_conf_pin_input_enable_get(struct pinctrl_dev * pctldev,const struct pinctrl_pin_desc * pin)232 static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev *pctldev,
233 const struct pinctrl_pin_desc *pin)
234 {
235 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
236 unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
237 unsigned int val;
238 int ret;
239
240 if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
241 /* This pin is always input-enabled. */
242 return 0;
243
244 ret = regmap_read(priv->regmap, UNIPHIER_PINCTRL_IECTRL, &val);
245 if (ret)
246 return ret;
247
248 return val & BIT(iectrl) ? 0 : -EINVAL;
249 }
250
uniphier_conf_pin_config_get(struct pinctrl_dev * pctldev,unsigned pin,unsigned long * configs)251 static int uniphier_conf_pin_config_get(struct pinctrl_dev *pctldev,
252 unsigned pin,
253 unsigned long *configs)
254 {
255 const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
256 enum pin_config_param param = pinconf_to_config_param(*configs);
257 bool has_arg = false;
258 u16 arg;
259 int ret;
260
261 switch (param) {
262 case PIN_CONFIG_BIAS_DISABLE:
263 case PIN_CONFIG_BIAS_PULL_UP:
264 case PIN_CONFIG_BIAS_PULL_DOWN:
265 ret = uniphier_conf_pin_bias_get(pctldev, pin_desc, param);
266 break;
267 case PIN_CONFIG_DRIVE_STRENGTH:
268 ret = uniphier_conf_pin_drive_get(pctldev, pin_desc, &arg);
269 has_arg = true;
270 break;
271 case PIN_CONFIG_INPUT_ENABLE:
272 ret = uniphier_conf_pin_input_enable_get(pctldev, pin_desc);
273 break;
274 default:
275 /* unsupported parameter */
276 ret = -EINVAL;
277 break;
278 }
279
280 if (ret == 0 && has_arg)
281 *configs = pinconf_to_config_packed(param, arg);
282
283 return ret;
284 }
285
uniphier_conf_pin_bias_set(struct pinctrl_dev * pctldev,const struct pinctrl_pin_desc * pin,enum pin_config_param param,u16 arg)286 static int uniphier_conf_pin_bias_set(struct pinctrl_dev *pctldev,
287 const struct pinctrl_pin_desc *pin,
288 enum pin_config_param param,
289 u16 arg)
290 {
291 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
292 enum uniphier_pin_pull_dir pull_dir =
293 uniphier_pin_get_pull_dir(pin->drv_data);
294 unsigned int pupdctrl, reg, shift;
295 unsigned int val = 1;
296
297 switch (param) {
298 case PIN_CONFIG_BIAS_DISABLE:
299 if (pull_dir == UNIPHIER_PIN_PULL_NONE)
300 return 0;
301 if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED ||
302 pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED) {
303 dev_err(pctldev->dev,
304 "can not disable pull register for pin %u (%s)\n",
305 pin->number, pin->name);
306 return -EINVAL;
307 }
308 val = 0;
309 break;
310 case PIN_CONFIG_BIAS_PULL_UP:
311 if (pull_dir == UNIPHIER_PIN_PULL_UP_FIXED && arg != 0)
312 return 0;
313 if (pull_dir != UNIPHIER_PIN_PULL_UP) {
314 dev_err(pctldev->dev,
315 "pull-up is unsupported for pin %u (%s)\n",
316 pin->number, pin->name);
317 return -EINVAL;
318 }
319 if (arg == 0) {
320 dev_err(pctldev->dev, "pull-up can not be total\n");
321 return -EINVAL;
322 }
323 break;
324 case PIN_CONFIG_BIAS_PULL_DOWN:
325 if (pull_dir == UNIPHIER_PIN_PULL_DOWN_FIXED && arg != 0)
326 return 0;
327 if (pull_dir != UNIPHIER_PIN_PULL_DOWN) {
328 dev_err(pctldev->dev,
329 "pull-down is unsupported for pin %u (%s)\n",
330 pin->number, pin->name);
331 return -EINVAL;
332 }
333 if (arg == 0) {
334 dev_err(pctldev->dev, "pull-down can not be total\n");
335 return -EINVAL;
336 }
337 break;
338 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
339 if (pull_dir == UNIPHIER_PIN_PULL_NONE) {
340 dev_err(pctldev->dev,
341 "pull-up/down is unsupported for pin %u (%s)\n",
342 pin->number, pin->name);
343 return -EINVAL;
344 }
345
346 if (arg == 0)
347 return 0; /* configuration ingored */
348 break;
349 default:
350 BUG();
351 }
352
353 pupdctrl = uniphier_pin_get_pupdctrl(pin->drv_data);
354
355 reg = UNIPHIER_PINCTRL_PUPDCTRL_BASE + pupdctrl / 32 * 4;
356 shift = pupdctrl % 32;
357
358 return regmap_update_bits(priv->regmap, reg, 1 << shift, val << shift);
359 }
360
uniphier_conf_pin_drive_set(struct pinctrl_dev * pctldev,const struct pinctrl_pin_desc * pin,u16 strength)361 static int uniphier_conf_pin_drive_set(struct pinctrl_dev *pctldev,
362 const struct pinctrl_pin_desc *pin,
363 u16 strength)
364 {
365 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
366 enum uniphier_pin_drv_str drv_str =
367 uniphier_pin_get_drv_str(pin->drv_data);
368 const unsigned int strength_4_8[] = {4, 8, -1};
369 const unsigned int strength_8_12_16_20[] = {8, 12, 16, 20, -1};
370 const unsigned int *supported_strength;
371 unsigned int drvctrl, reg, shift, mask, width, val;
372
373 switch (drv_str) {
374 case UNIPHIER_PIN_DRV_4_8:
375 supported_strength = strength_4_8;
376 width = 1;
377 break;
378 case UNIPHIER_PIN_DRV_8_12_16_20:
379 supported_strength = strength_8_12_16_20;
380 width = 2;
381 break;
382 default:
383 dev_err(pctldev->dev,
384 "cannot change drive strength for pin %u (%s)\n",
385 pin->number, pin->name);
386 return -EINVAL;
387 }
388
389 for (val = 0; supported_strength[val] > 0; val++) {
390 if (supported_strength[val] > strength)
391 break;
392 }
393
394 if (val == 0) {
395 dev_err(pctldev->dev,
396 "unsupported drive strength %u mA for pin %u (%s)\n",
397 strength, pin->number, pin->name);
398 return -EINVAL;
399 }
400
401 val--;
402
403 drvctrl = uniphier_pin_get_drvctrl(pin->drv_data);
404 drvctrl *= width;
405
406 reg = (width == 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE :
407 UNIPHIER_PINCTRL_DRVCTRL_BASE;
408
409 reg += drvctrl / 32 * 4;
410 shift = drvctrl % 32;
411 mask = (1U << width) - 1;
412
413 return regmap_update_bits(priv->regmap, reg,
414 mask << shift, val << shift);
415 }
416
uniphier_conf_pin_input_enable(struct pinctrl_dev * pctldev,const struct pinctrl_pin_desc * pin,u16 enable)417 static int uniphier_conf_pin_input_enable(struct pinctrl_dev *pctldev,
418 const struct pinctrl_pin_desc *pin,
419 u16 enable)
420 {
421 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
422 unsigned int iectrl = uniphier_pin_get_iectrl(pin->drv_data);
423
424 if (enable == 0) {
425 /*
426 * Multiple pins share one input enable, so per-pin disabling
427 * is impossible.
428 */
429 dev_err(pctldev->dev, "unable to disable input\n");
430 return -EINVAL;
431 }
432
433 if (iectrl == UNIPHIER_PIN_IECTRL_NONE)
434 /* This pin is always input-enabled. nothing to do. */
435 return 0;
436
437 return regmap_update_bits(priv->regmap, UNIPHIER_PINCTRL_IECTRL,
438 BIT(iectrl), BIT(iectrl));
439 }
440
uniphier_conf_pin_config_set(struct pinctrl_dev * pctldev,unsigned pin,unsigned long * configs,unsigned num_configs)441 static int uniphier_conf_pin_config_set(struct pinctrl_dev *pctldev,
442 unsigned pin,
443 unsigned long *configs,
444 unsigned num_configs)
445 {
446 const struct pinctrl_pin_desc *pin_desc = &pctldev->desc->pins[pin];
447 int i, ret;
448
449 for (i = 0; i < num_configs; i++) {
450 enum pin_config_param param =
451 pinconf_to_config_param(configs[i]);
452 u16 arg = pinconf_to_config_argument(configs[i]);
453
454 switch (param) {
455 case PIN_CONFIG_BIAS_DISABLE:
456 case PIN_CONFIG_BIAS_PULL_UP:
457 case PIN_CONFIG_BIAS_PULL_DOWN:
458 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
459 ret = uniphier_conf_pin_bias_set(pctldev, pin_desc,
460 param, arg);
461 break;
462 case PIN_CONFIG_DRIVE_STRENGTH:
463 ret = uniphier_conf_pin_drive_set(pctldev, pin_desc,
464 arg);
465 break;
466 case PIN_CONFIG_INPUT_ENABLE:
467 ret = uniphier_conf_pin_input_enable(pctldev,
468 pin_desc, arg);
469 break;
470 default:
471 dev_err(pctldev->dev,
472 "unsupported configuration parameter %u\n",
473 param);
474 return -EINVAL;
475 }
476
477 if (ret)
478 return ret;
479 }
480
481 return 0;
482 }
483
uniphier_conf_pin_config_group_set(struct pinctrl_dev * pctldev,unsigned selector,unsigned long * configs,unsigned num_configs)484 static int uniphier_conf_pin_config_group_set(struct pinctrl_dev *pctldev,
485 unsigned selector,
486 unsigned long *configs,
487 unsigned num_configs)
488 {
489 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
490 const unsigned *pins = priv->socdata->groups[selector].pins;
491 unsigned num_pins = priv->socdata->groups[selector].num_pins;
492 int i, ret;
493
494 for (i = 0; i < num_pins; i++) {
495 ret = uniphier_conf_pin_config_set(pctldev, pins[i],
496 configs, num_configs);
497 if (ret)
498 return ret;
499 }
500
501 return 0;
502 }
503
504 static const struct pinconf_ops uniphier_confops = {
505 .is_generic = true,
506 .pin_config_get = uniphier_conf_pin_config_get,
507 .pin_config_set = uniphier_conf_pin_config_set,
508 .pin_config_group_set = uniphier_conf_pin_config_group_set,
509 };
510
uniphier_pmx_get_functions_count(struct pinctrl_dev * pctldev)511 static int uniphier_pmx_get_functions_count(struct pinctrl_dev *pctldev)
512 {
513 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
514
515 return priv->socdata->functions_count;
516 }
517
uniphier_pmx_get_function_name(struct pinctrl_dev * pctldev,unsigned selector)518 static const char *uniphier_pmx_get_function_name(struct pinctrl_dev *pctldev,
519 unsigned selector)
520 {
521 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
522
523 return priv->socdata->functions[selector].name;
524 }
525
uniphier_pmx_get_function_groups(struct pinctrl_dev * pctldev,unsigned selector,const char * const ** groups,unsigned * num_groups)526 static int uniphier_pmx_get_function_groups(struct pinctrl_dev *pctldev,
527 unsigned selector,
528 const char * const **groups,
529 unsigned *num_groups)
530 {
531 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
532
533 *groups = priv->socdata->functions[selector].groups;
534 *num_groups = priv->socdata->functions[selector].num_groups;
535
536 return 0;
537 }
538
uniphier_pmx_set_one_mux(struct pinctrl_dev * pctldev,unsigned pin,unsigned muxval)539 static int uniphier_pmx_set_one_mux(struct pinctrl_dev *pctldev, unsigned pin,
540 unsigned muxval)
541 {
542 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
543 unsigned mux_bits = priv->socdata->mux_bits;
544 unsigned reg_stride = priv->socdata->reg_stride;
545 unsigned reg, reg_end, shift, mask;
546 int ret;
547
548 /* some pins need input-enabling */
549 ret = uniphier_conf_pin_input_enable(pctldev,
550 &pctldev->desc->pins[pin], 1);
551 if (ret)
552 return ret;
553
554 reg = UNIPHIER_PINCTRL_PINMUX_BASE + pin * mux_bits / 32 * reg_stride;
555 reg_end = reg + reg_stride;
556 shift = pin * mux_bits % 32;
557 mask = (1U << mux_bits) - 1;
558
559 /*
560 * If reg_stride is greater than 4, the MSB of each pinsel shall be
561 * stored in the offset+4.
562 */
563 for (; reg < reg_end; reg += 4) {
564 ret = regmap_update_bits(priv->regmap, reg,
565 mask << shift, muxval << shift);
566 if (ret)
567 return ret;
568 muxval >>= mux_bits;
569 }
570
571 if (priv->socdata->load_pinctrl) {
572 ret = regmap_write(priv->regmap,
573 UNIPHIER_PINCTRL_LOAD_PINMUX, 1);
574 if (ret)
575 return ret;
576 }
577
578 return 0;
579 }
580
uniphier_pmx_set_mux(struct pinctrl_dev * pctldev,unsigned func_selector,unsigned group_selector)581 static int uniphier_pmx_set_mux(struct pinctrl_dev *pctldev,
582 unsigned func_selector,
583 unsigned group_selector)
584 {
585 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
586 const struct uniphier_pinctrl_group *grp =
587 &priv->socdata->groups[group_selector];
588 int i;
589 int ret;
590
591 for (i = 0; i < grp->num_pins; i++) {
592 ret = uniphier_pmx_set_one_mux(pctldev, grp->pins[i],
593 grp->muxvals[i]);
594 if (ret)
595 return ret;
596 }
597
598 return 0;
599 }
600
uniphier_pmx_gpio_request_enable(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned offset)601 static int uniphier_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
602 struct pinctrl_gpio_range *range,
603 unsigned offset)
604 {
605 struct uniphier_pinctrl_priv *priv = pinctrl_dev_get_drvdata(pctldev);
606 const struct uniphier_pinctrl_group *groups = priv->socdata->groups;
607 int groups_count = priv->socdata->groups_count;
608 enum uniphier_pinmux_gpio_range_type range_type;
609 int i, j;
610
611 if (strstr(range->name, "irq"))
612 range_type = UNIPHIER_PINMUX_GPIO_RANGE_IRQ;
613 else
614 range_type = UNIPHIER_PINMUX_GPIO_RANGE_PORT;
615
616 for (i = 0; i < groups_count; i++) {
617 if (groups[i].range_type != range_type)
618 continue;
619
620 for (j = 0; j < groups[i].num_pins; j++)
621 if (groups[i].pins[j] == offset)
622 goto found;
623 }
624
625 dev_err(pctldev->dev, "pin %u does not support GPIO\n", offset);
626 return -EINVAL;
627
628 found:
629 return uniphier_pmx_set_one_mux(pctldev, offset, groups[i].muxvals[j]);
630 }
631
632 static const struct pinmux_ops uniphier_pmxops = {
633 .get_functions_count = uniphier_pmx_get_functions_count,
634 .get_function_name = uniphier_pmx_get_function_name,
635 .get_function_groups = uniphier_pmx_get_function_groups,
636 .set_mux = uniphier_pmx_set_mux,
637 .gpio_request_enable = uniphier_pmx_gpio_request_enable,
638 .strict = true,
639 };
640
uniphier_pinctrl_probe(struct platform_device * pdev,struct pinctrl_desc * desc,struct uniphier_pinctrl_socdata * socdata)641 int uniphier_pinctrl_probe(struct platform_device *pdev,
642 struct pinctrl_desc *desc,
643 struct uniphier_pinctrl_socdata *socdata)
644 {
645 struct device *dev = &pdev->dev;
646 struct uniphier_pinctrl_priv *priv;
647
648 if (!socdata ||
649 !socdata->groups ||
650 !socdata->groups_count ||
651 !socdata->functions ||
652 !socdata->functions_count ||
653 !socdata->mux_bits ||
654 !socdata->reg_stride) {
655 dev_err(dev, "pinctrl socdata lacks necessary members\n");
656 return -EINVAL;
657 }
658
659 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
660 if (!priv)
661 return -ENOMEM;
662
663 priv->regmap = syscon_node_to_regmap(dev->of_node);
664 if (IS_ERR(priv->regmap)) {
665 dev_err(dev, "failed to get regmap\n");
666 return PTR_ERR(priv->regmap);
667 }
668
669 priv->socdata = socdata;
670 desc->pctlops = &uniphier_pctlops;
671 desc->pmxops = &uniphier_pmxops;
672 desc->confops = &uniphier_confops;
673
674 priv->pctldev = pinctrl_register(desc, dev, priv);
675 if (IS_ERR(priv->pctldev)) {
676 dev_err(dev, "failed to register UniPhier pinctrl driver\n");
677 return PTR_ERR(priv->pctldev);
678 }
679
680 platform_set_drvdata(pdev, priv);
681
682 return 0;
683 }
684 EXPORT_SYMBOL_GPL(uniphier_pinctrl_probe);
685
uniphier_pinctrl_remove(struct platform_device * pdev)686 int uniphier_pinctrl_remove(struct platform_device *pdev)
687 {
688 struct uniphier_pinctrl_priv *priv = platform_get_drvdata(pdev);
689
690 pinctrl_unregister(priv->pctldev);
691
692 return 0;
693 }
694 EXPORT_SYMBOL_GPL(uniphier_pinctrl_remove);
695