2 * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
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.
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.
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>
25 #include "../pinctrl-utils.h"
26 #include "pinctrl-uniphier.h"
28 struct uniphier_pinctrl_priv
{
29 struct pinctrl_dev
*pctldev
;
30 struct regmap
*regmap
;
31 struct uniphier_pinctrl_socdata
*socdata
;
34 static int uniphier_pctl_get_groups_count(struct pinctrl_dev
*pctldev
)
36 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
38 return priv
->socdata
->groups_count
;
41 static const char *uniphier_pctl_get_group_name(struct pinctrl_dev
*pctldev
,
44 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
46 return priv
->socdata
->groups
[selector
].name
;
49 static int uniphier_pctl_get_group_pins(struct pinctrl_dev
*pctldev
,
51 const unsigned **pins
,
54 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
56 *pins
= priv
->socdata
->groups
[selector
].pins
;
57 *num_pins
= priv
->socdata
->groups
[selector
].num_pins
;
62 #ifdef CONFIG_DEBUG_FS
63 static void uniphier_pctl_pin_dbg_show(struct pinctrl_dev
*pctldev
,
64 struct seq_file
*s
, unsigned offset
)
66 const struct pinctrl_pin_desc
*pin
= &pctldev
->desc
->pins
[offset
];
67 const char *pull_dir
, *drv_str
;
69 switch (uniphier_pin_get_pull_dir(pin
->drv_data
)) {
70 case UNIPHIER_PIN_PULL_UP
:
73 case UNIPHIER_PIN_PULL_DOWN
:
76 case UNIPHIER_PIN_PULL_NONE
:
83 switch (uniphier_pin_get_drv_str(pin
->drv_data
)) {
84 case UNIPHIER_PIN_DRV_4_8
:
87 case UNIPHIER_PIN_DRV_8_12_16_20
:
88 drv_str
= "8/12/16/20(mA)";
90 case UNIPHIER_PIN_DRV_FIXED_4
:
93 case UNIPHIER_PIN_DRV_FIXED_5
:
96 case UNIPHIER_PIN_DRV_FIXED_8
:
99 case UNIPHIER_PIN_DRV_NONE
:
106 seq_printf(s
, " PULL_DIR=%s DRV_STR=%s", pull_dir
, drv_str
);
110 static const struct pinctrl_ops uniphier_pctlops
= {
111 .get_groups_count
= uniphier_pctl_get_groups_count
,
112 .get_group_name
= uniphier_pctl_get_group_name
,
113 .get_group_pins
= uniphier_pctl_get_group_pins
,
114 #ifdef CONFIG_DEBUG_FS
115 .pin_dbg_show
= uniphier_pctl_pin_dbg_show
,
117 .dt_node_to_map
= pinconf_generic_dt_node_to_map_all
,
118 .dt_free_map
= pinctrl_utils_dt_free_map
,
121 static int uniphier_conf_pin_bias_get(struct pinctrl_dev
*pctldev
,
122 const struct pinctrl_pin_desc
*pin
,
123 enum pin_config_param param
)
125 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
126 enum uniphier_pin_pull_dir pull_dir
=
127 uniphier_pin_get_pull_dir(pin
->drv_data
);
128 unsigned int pupdctrl
, reg
, shift
, val
;
129 unsigned int expected
= 1;
133 case PIN_CONFIG_BIAS_DISABLE
:
134 if (pull_dir
== UNIPHIER_PIN_PULL_NONE
)
136 if (pull_dir
== UNIPHIER_PIN_PULL_UP_FIXED
||
137 pull_dir
== UNIPHIER_PIN_PULL_DOWN_FIXED
)
141 case PIN_CONFIG_BIAS_PULL_UP
:
142 if (pull_dir
== UNIPHIER_PIN_PULL_UP_FIXED
)
144 if (pull_dir
!= UNIPHIER_PIN_PULL_UP
)
147 case PIN_CONFIG_BIAS_PULL_DOWN
:
148 if (pull_dir
== UNIPHIER_PIN_PULL_DOWN_FIXED
)
150 if (pull_dir
!= UNIPHIER_PIN_PULL_DOWN
)
157 pupdctrl
= uniphier_pin_get_pupdctrl(pin
->drv_data
);
159 reg
= UNIPHIER_PINCTRL_PUPDCTRL_BASE
+ pupdctrl
/ 32 * 4;
160 shift
= pupdctrl
% 32;
162 ret
= regmap_read(priv
->regmap
, reg
, &val
);
166 val
= (val
>> shift
) & 1;
168 return (val
== expected
) ? 0 : -EINVAL
;
171 static int uniphier_conf_pin_drive_get(struct pinctrl_dev
*pctldev
,
172 const struct pinctrl_pin_desc
*pin
,
175 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
176 enum uniphier_pin_drv_str drv_str
=
177 uniphier_pin_get_drv_str(pin
->drv_data
);
178 const unsigned int strength_4_8
[] = {4, 8};
179 const unsigned int strength_8_12_16_20
[] = {8, 12, 16, 20};
180 const unsigned int *supported_strength
;
181 unsigned int drvctrl
, reg
, shift
, mask
, width
, val
;
185 case UNIPHIER_PIN_DRV_4_8
:
186 supported_strength
= strength_4_8
;
189 case UNIPHIER_PIN_DRV_8_12_16_20
:
190 supported_strength
= strength_8_12_16_20
;
193 case UNIPHIER_PIN_DRV_FIXED_4
:
196 case UNIPHIER_PIN_DRV_FIXED_5
:
199 case UNIPHIER_PIN_DRV_FIXED_8
:
203 /* drive strength control is not supported for this pin */
207 drvctrl
= uniphier_pin_get_drvctrl(pin
->drv_data
);
210 reg
= (width
== 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE
:
211 UNIPHIER_PINCTRL_DRVCTRL_BASE
;
213 reg
+= drvctrl
/ 32 * 4;
214 shift
= drvctrl
% 32;
215 mask
= (1U << width
) - 1;
217 ret
= regmap_read(priv
->regmap
, reg
, &val
);
221 *strength
= supported_strength
[(val
>> shift
) & mask
];
226 static int uniphier_conf_pin_input_enable_get(struct pinctrl_dev
*pctldev
,
227 const struct pinctrl_pin_desc
*pin
)
229 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
230 unsigned int iectrl
= uniphier_pin_get_iectrl(pin
->drv_data
);
234 if (iectrl
== UNIPHIER_PIN_IECTRL_NONE
)
235 /* This pin is always input-enabled. */
238 ret
= regmap_read(priv
->regmap
, UNIPHIER_PINCTRL_IECTRL
, &val
);
242 return val
& BIT(iectrl
) ? 0 : -EINVAL
;
245 static int uniphier_conf_pin_config_get(struct pinctrl_dev
*pctldev
,
247 unsigned long *configs
)
249 const struct pinctrl_pin_desc
*pin_desc
= &pctldev
->desc
->pins
[pin
];
250 enum pin_config_param param
= pinconf_to_config_param(*configs
);
251 bool has_arg
= false;
256 case PIN_CONFIG_BIAS_DISABLE
:
257 case PIN_CONFIG_BIAS_PULL_UP
:
258 case PIN_CONFIG_BIAS_PULL_DOWN
:
259 ret
= uniphier_conf_pin_bias_get(pctldev
, pin_desc
, param
);
261 case PIN_CONFIG_DRIVE_STRENGTH
:
262 ret
= uniphier_conf_pin_drive_get(pctldev
, pin_desc
, &arg
);
265 case PIN_CONFIG_INPUT_ENABLE
:
266 ret
= uniphier_conf_pin_input_enable_get(pctldev
, pin_desc
);
269 /* unsupported parameter */
274 if (ret
== 0 && has_arg
)
275 *configs
= pinconf_to_config_packed(param
, arg
);
280 static int uniphier_conf_pin_bias_set(struct pinctrl_dev
*pctldev
,
281 const struct pinctrl_pin_desc
*pin
,
282 enum pin_config_param param
,
285 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
286 enum uniphier_pin_pull_dir pull_dir
=
287 uniphier_pin_get_pull_dir(pin
->drv_data
);
288 unsigned int pupdctrl
, reg
, shift
;
289 unsigned int val
= 1;
292 case PIN_CONFIG_BIAS_DISABLE
:
293 if (pull_dir
== UNIPHIER_PIN_PULL_NONE
)
295 if (pull_dir
== UNIPHIER_PIN_PULL_UP_FIXED
||
296 pull_dir
== UNIPHIER_PIN_PULL_DOWN_FIXED
) {
297 dev_err(pctldev
->dev
,
298 "can not disable pull register for pin %u (%s)\n",
299 pin
->number
, pin
->name
);
304 case PIN_CONFIG_BIAS_PULL_UP
:
305 if (pull_dir
== UNIPHIER_PIN_PULL_UP_FIXED
&& arg
!= 0)
307 if (pull_dir
!= UNIPHIER_PIN_PULL_UP
) {
308 dev_err(pctldev
->dev
,
309 "pull-up is unsupported for pin %u (%s)\n",
310 pin
->number
, pin
->name
);
314 dev_err(pctldev
->dev
, "pull-up can not be total\n");
318 case PIN_CONFIG_BIAS_PULL_DOWN
:
319 if (pull_dir
== UNIPHIER_PIN_PULL_DOWN_FIXED
&& arg
!= 0)
321 if (pull_dir
!= UNIPHIER_PIN_PULL_DOWN
) {
322 dev_err(pctldev
->dev
,
323 "pull-down is unsupported for pin %u (%s)\n",
324 pin
->number
, pin
->name
);
328 dev_err(pctldev
->dev
, "pull-down can not be total\n");
332 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
:
333 if (pull_dir
== UNIPHIER_PIN_PULL_NONE
) {
334 dev_err(pctldev
->dev
,
335 "pull-up/down is unsupported for pin %u (%s)\n",
336 pin
->number
, pin
->name
);
341 return 0; /* configuration ingored */
347 pupdctrl
= uniphier_pin_get_pupdctrl(pin
->drv_data
);
349 reg
= UNIPHIER_PINCTRL_PUPDCTRL_BASE
+ pupdctrl
/ 32 * 4;
350 shift
= pupdctrl
% 32;
352 return regmap_update_bits(priv
->regmap
, reg
, 1 << shift
, val
<< shift
);
355 static int uniphier_conf_pin_drive_set(struct pinctrl_dev
*pctldev
,
356 const struct pinctrl_pin_desc
*pin
,
359 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
360 enum uniphier_pin_drv_str drv_str
=
361 uniphier_pin_get_drv_str(pin
->drv_data
);
362 const unsigned int strength_4_8
[] = {4, 8, -1};
363 const unsigned int strength_8_12_16_20
[] = {8, 12, 16, 20, -1};
364 const unsigned int *supported_strength
;
365 unsigned int drvctrl
, reg
, shift
, mask
, width
, val
;
368 case UNIPHIER_PIN_DRV_4_8
:
369 supported_strength
= strength_4_8
;
372 case UNIPHIER_PIN_DRV_8_12_16_20
:
373 supported_strength
= strength_8_12_16_20
;
377 dev_err(pctldev
->dev
,
378 "cannot change drive strength for pin %u (%s)\n",
379 pin
->number
, pin
->name
);
383 for (val
= 0; supported_strength
[val
] > 0; val
++) {
384 if (supported_strength
[val
] > strength
)
389 dev_err(pctldev
->dev
,
390 "unsupported drive strength %u mA for pin %u (%s)\n",
391 strength
, pin
->number
, pin
->name
);
397 drvctrl
= uniphier_pin_get_drvctrl(pin
->drv_data
);
400 reg
= (width
== 2) ? UNIPHIER_PINCTRL_DRV2CTRL_BASE
:
401 UNIPHIER_PINCTRL_DRVCTRL_BASE
;
403 reg
+= drvctrl
/ 32 * 4;
404 shift
= drvctrl
% 32;
405 mask
= (1U << width
) - 1;
407 return regmap_update_bits(priv
->regmap
, reg
,
408 mask
<< shift
, val
<< shift
);
411 static int uniphier_conf_pin_input_enable(struct pinctrl_dev
*pctldev
,
412 const struct pinctrl_pin_desc
*pin
,
415 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
416 unsigned int iectrl
= uniphier_pin_get_iectrl(pin
->drv_data
);
420 * Multiple pins share one input enable, so per-pin disabling
423 dev_err(pctldev
->dev
, "unable to disable input\n");
427 if (iectrl
== UNIPHIER_PIN_IECTRL_NONE
)
428 /* This pin is always input-enabled. nothing to do. */
431 return regmap_update_bits(priv
->regmap
, UNIPHIER_PINCTRL_IECTRL
,
432 BIT(iectrl
), BIT(iectrl
));
435 static int uniphier_conf_pin_config_set(struct pinctrl_dev
*pctldev
,
437 unsigned long *configs
,
438 unsigned num_configs
)
440 const struct pinctrl_pin_desc
*pin_desc
= &pctldev
->desc
->pins
[pin
];
443 for (i
= 0; i
< num_configs
; i
++) {
444 enum pin_config_param param
=
445 pinconf_to_config_param(configs
[i
]);
446 u16 arg
= pinconf_to_config_argument(configs
[i
]);
449 case PIN_CONFIG_BIAS_DISABLE
:
450 case PIN_CONFIG_BIAS_PULL_UP
:
451 case PIN_CONFIG_BIAS_PULL_DOWN
:
452 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
:
453 ret
= uniphier_conf_pin_bias_set(pctldev
, pin_desc
,
456 case PIN_CONFIG_DRIVE_STRENGTH
:
457 ret
= uniphier_conf_pin_drive_set(pctldev
, pin_desc
,
460 case PIN_CONFIG_INPUT_ENABLE
:
461 ret
= uniphier_conf_pin_input_enable(pctldev
,
465 dev_err(pctldev
->dev
,
466 "unsupported configuration parameter %u\n",
478 static int uniphier_conf_pin_config_group_set(struct pinctrl_dev
*pctldev
,
480 unsigned long *configs
,
481 unsigned num_configs
)
483 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
484 const unsigned *pins
= priv
->socdata
->groups
[selector
].pins
;
485 unsigned num_pins
= priv
->socdata
->groups
[selector
].num_pins
;
488 for (i
= 0; i
< num_pins
; i
++) {
489 ret
= uniphier_conf_pin_config_set(pctldev
, pins
[i
],
490 configs
, num_configs
);
498 static const struct pinconf_ops uniphier_confops
= {
500 .pin_config_get
= uniphier_conf_pin_config_get
,
501 .pin_config_set
= uniphier_conf_pin_config_set
,
502 .pin_config_group_set
= uniphier_conf_pin_config_group_set
,
505 static int uniphier_pmx_get_functions_count(struct pinctrl_dev
*pctldev
)
507 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
509 return priv
->socdata
->functions_count
;
512 static const char *uniphier_pmx_get_function_name(struct pinctrl_dev
*pctldev
,
515 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
517 return priv
->socdata
->functions
[selector
].name
;
520 static int uniphier_pmx_get_function_groups(struct pinctrl_dev
*pctldev
,
522 const char * const **groups
,
523 unsigned *num_groups
)
525 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
527 *groups
= priv
->socdata
->functions
[selector
].groups
;
528 *num_groups
= priv
->socdata
->functions
[selector
].num_groups
;
533 static int uniphier_pmx_set_one_mux(struct pinctrl_dev
*pctldev
, unsigned pin
,
536 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
537 unsigned mux_bits
= priv
->socdata
->mux_bits
;
538 unsigned reg_stride
= priv
->socdata
->reg_stride
;
539 unsigned reg
, reg_end
, shift
, mask
;
542 /* some pins need input-enabling */
543 ret
= uniphier_conf_pin_input_enable(pctldev
,
544 &pctldev
->desc
->pins
[pin
], 1);
548 reg
= UNIPHIER_PINCTRL_PINMUX_BASE
+ pin
* mux_bits
/ 32 * reg_stride
;
549 reg_end
= reg
+ reg_stride
;
550 shift
= pin
* mux_bits
% 32;
551 mask
= (1U << mux_bits
) - 1;
554 * If reg_stride is greater than 4, the MSB of each pinsel shall be
555 * stored in the offset+4.
557 for (; reg
< reg_end
; reg
+= 4) {
558 ret
= regmap_update_bits(priv
->regmap
, reg
,
559 mask
<< shift
, muxval
<< shift
);
565 if (priv
->socdata
->load_pinctrl
) {
566 ret
= regmap_write(priv
->regmap
,
567 UNIPHIER_PINCTRL_LOAD_PINMUX
, 1);
575 static int uniphier_pmx_set_mux(struct pinctrl_dev
*pctldev
,
576 unsigned func_selector
,
577 unsigned group_selector
)
579 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
580 const struct uniphier_pinctrl_group
*grp
=
581 &priv
->socdata
->groups
[group_selector
];
585 for (i
= 0; i
< grp
->num_pins
; i
++) {
586 ret
= uniphier_pmx_set_one_mux(pctldev
, grp
->pins
[i
],
595 static int uniphier_pmx_gpio_request_enable(struct pinctrl_dev
*pctldev
,
596 struct pinctrl_gpio_range
*range
,
599 struct uniphier_pinctrl_priv
*priv
= pinctrl_dev_get_drvdata(pctldev
);
600 const struct uniphier_pinctrl_group
*groups
= priv
->socdata
->groups
;
601 int groups_count
= priv
->socdata
->groups_count
;
602 enum uniphier_pinmux_gpio_range_type range_type
;
605 if (strstr(range
->name
, "irq"))
606 range_type
= UNIPHIER_PINMUX_GPIO_RANGE_IRQ
;
608 range_type
= UNIPHIER_PINMUX_GPIO_RANGE_PORT
;
610 for (i
= 0; i
< groups_count
; i
++) {
611 if (groups
[i
].range_type
!= range_type
)
614 for (j
= 0; j
< groups
[i
].num_pins
; j
++)
615 if (groups
[i
].pins
[j
] == offset
)
619 dev_err(pctldev
->dev
, "pin %u does not support GPIO\n", offset
);
623 return uniphier_pmx_set_one_mux(pctldev
, offset
, groups
[i
].muxvals
[j
]);
626 static const struct pinmux_ops uniphier_pmxops
= {
627 .get_functions_count
= uniphier_pmx_get_functions_count
,
628 .get_function_name
= uniphier_pmx_get_function_name
,
629 .get_function_groups
= uniphier_pmx_get_function_groups
,
630 .set_mux
= uniphier_pmx_set_mux
,
631 .gpio_request_enable
= uniphier_pmx_gpio_request_enable
,
635 int uniphier_pinctrl_probe(struct platform_device
*pdev
,
636 struct pinctrl_desc
*desc
,
637 struct uniphier_pinctrl_socdata
*socdata
)
639 struct device
*dev
= &pdev
->dev
;
640 struct uniphier_pinctrl_priv
*priv
;
644 !socdata
->groups_count
||
645 !socdata
->functions
||
646 !socdata
->functions_count
||
647 !socdata
->mux_bits
||
648 !socdata
->reg_stride
) {
649 dev_err(dev
, "pinctrl socdata lacks necessary members\n");
653 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
657 priv
->regmap
= syscon_node_to_regmap(dev
->of_node
);
658 if (IS_ERR(priv
->regmap
)) {
659 dev_err(dev
, "failed to get regmap\n");
660 return PTR_ERR(priv
->regmap
);
663 priv
->socdata
= socdata
;
664 desc
->pctlops
= &uniphier_pctlops
;
665 desc
->pmxops
= &uniphier_pmxops
;
666 desc
->confops
= &uniphier_confops
;
668 priv
->pctldev
= pinctrl_register(desc
, dev
, priv
);
669 if (IS_ERR(priv
->pctldev
)) {
670 dev_err(dev
, "failed to register UniPhier pinctrl driver\n");
671 return PTR_ERR(priv
->pctldev
);
674 platform_set_drvdata(pdev
, priv
);
678 EXPORT_SYMBOL_GPL(uniphier_pinctrl_probe
);
680 int uniphier_pinctrl_remove(struct platform_device
*pdev
)
682 struct uniphier_pinctrl_priv
*priv
= platform_get_drvdata(pdev
);
684 pinctrl_unregister(priv
->pctldev
);
688 EXPORT_SYMBOL_GPL(uniphier_pinctrl_remove
);