1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2016 IBM Corp.
6 #include <linux/mfd/syscon.h>
7 #include <linux/platform_device.h>
8 #include <linux/slab.h>
9 #include <linux/string.h>
11 #include "pinctrl-aspeed.h"
13 int aspeed_pinctrl_get_groups_count(struct pinctrl_dev
*pctldev
)
15 struct aspeed_pinctrl_data
*pdata
= pinctrl_dev_get_drvdata(pctldev
);
17 return pdata
->pinmux
.ngroups
;
20 const char *aspeed_pinctrl_get_group_name(struct pinctrl_dev
*pctldev
,
23 struct aspeed_pinctrl_data
*pdata
= pinctrl_dev_get_drvdata(pctldev
);
25 return pdata
->pinmux
.groups
[group
].name
;
28 int aspeed_pinctrl_get_group_pins(struct pinctrl_dev
*pctldev
,
29 unsigned int group
, const unsigned int **pins
,
32 struct aspeed_pinctrl_data
*pdata
= pinctrl_dev_get_drvdata(pctldev
);
34 *pins
= &pdata
->pinmux
.groups
[group
].pins
[0];
35 *npins
= pdata
->pinmux
.groups
[group
].npins
;
40 void aspeed_pinctrl_pin_dbg_show(struct pinctrl_dev
*pctldev
,
41 struct seq_file
*s
, unsigned int offset
)
43 seq_printf(s
, " %s", dev_name(pctldev
->dev
));
46 int aspeed_pinmux_get_fn_count(struct pinctrl_dev
*pctldev
)
48 struct aspeed_pinctrl_data
*pdata
= pinctrl_dev_get_drvdata(pctldev
);
50 return pdata
->pinmux
.nfunctions
;
53 const char *aspeed_pinmux_get_fn_name(struct pinctrl_dev
*pctldev
,
54 unsigned int function
)
56 struct aspeed_pinctrl_data
*pdata
= pinctrl_dev_get_drvdata(pctldev
);
58 return pdata
->pinmux
.functions
[function
].name
;
61 int aspeed_pinmux_get_fn_groups(struct pinctrl_dev
*pctldev
,
62 unsigned int function
,
63 const char * const **groups
,
64 unsigned int * const num_groups
)
66 struct aspeed_pinctrl_data
*pdata
= pinctrl_dev_get_drvdata(pctldev
);
68 *groups
= pdata
->pinmux
.functions
[function
].groups
;
69 *num_groups
= pdata
->pinmux
.functions
[function
].ngroups
;
74 static int aspeed_sig_expr_enable(struct aspeed_pinmux_data
*ctx
,
75 const struct aspeed_sig_expr
*expr
)
79 ret
= aspeed_sig_expr_eval(ctx
, expr
, true);
84 return aspeed_sig_expr_set(ctx
, expr
, true);
89 static int aspeed_sig_expr_disable(struct aspeed_pinmux_data
*ctx
,
90 const struct aspeed_sig_expr
*expr
)
94 ret
= aspeed_sig_expr_eval(ctx
, expr
, true);
99 return aspeed_sig_expr_set(ctx
, expr
, false);
105 * Disable a signal on a pin by disabling all provided signal expressions.
107 * @ctx: The pinmux context
108 * @exprs: The list of signal expressions (from a priority level on a pin)
110 * Return: 0 if all expressions are disabled, otherwise a negative error code
112 static int aspeed_disable_sig(struct aspeed_pinmux_data
*ctx
,
113 const struct aspeed_sig_expr
**exprs
)
120 while (*exprs
&& !ret
) {
121 ret
= aspeed_sig_expr_disable(ctx
, *exprs
);
129 * Search for the signal expression needed to enable the pin's signal for the
130 * requested function.
132 * @exprs: List of signal expressions (haystack)
133 * @name: The name of the requested function (needle)
135 * Return: A pointer to the signal expression whose function tag matches the
136 * provided name, otherwise NULL.
139 static const struct aspeed_sig_expr
*aspeed_find_expr_by_name(
140 const struct aspeed_sig_expr
**exprs
, const char *name
)
143 if (strcmp((*exprs
)->function
, name
) == 0)
151 static char *get_defined_attribute(const struct aspeed_pin_desc
*pdesc
,
153 const struct aspeed_sig_expr
*))
157 const struct aspeed_sig_expr
***prios
, **funcs
, *expr
;
159 prios
= pdesc
->prios
;
161 while ((funcs
= *prios
)) {
162 while ((expr
= *funcs
)) {
163 const char *str
= get(expr
);
164 size_t delta
= strlen(str
) + 2;
167 expanded
= krealloc(found
, len
+ delta
+ 1, GFP_KERNEL
);
190 found
[len
- 2] = '\0';
195 static const char *aspeed_sig_expr_function(const struct aspeed_sig_expr
*expr
)
197 return expr
->function
;
200 static char *get_defined_functions(const struct aspeed_pin_desc
*pdesc
)
202 return get_defined_attribute(pdesc
, aspeed_sig_expr_function
);
205 static const char *aspeed_sig_expr_signal(const struct aspeed_sig_expr
*expr
)
210 static char *get_defined_signals(const struct aspeed_pin_desc
*pdesc
)
212 return get_defined_attribute(pdesc
, aspeed_sig_expr_signal
);
215 int aspeed_pinmux_set_mux(struct pinctrl_dev
*pctldev
, unsigned int function
,
220 struct aspeed_pinctrl_data
*pdata
= pinctrl_dev_get_drvdata(pctldev
);
221 const struct aspeed_pin_group
*pgroup
= &pdata
->pinmux
.groups
[group
];
222 const struct aspeed_pin_function
*pfunc
=
223 &pdata
->pinmux
.functions
[function
];
225 for (i
= 0; i
< pgroup
->npins
; i
++) {
226 int pin
= pgroup
->pins
[i
];
227 const struct aspeed_pin_desc
*pdesc
= pdata
->pins
[pin
].drv_data
;
228 const struct aspeed_sig_expr
*expr
= NULL
;
229 const struct aspeed_sig_expr
**funcs
;
230 const struct aspeed_sig_expr
***prios
;
232 pr_debug("Muxing pin %d for %s\n", pin
, pfunc
->name
);
237 prios
= pdesc
->prios
;
242 /* Disable functions at a higher priority than that requested */
243 while ((funcs
= *prios
)) {
244 expr
= aspeed_find_expr_by_name(funcs
, pfunc
->name
);
249 ret
= aspeed_disable_sig(&pdata
->pinmux
, funcs
);
257 char *functions
= get_defined_functions(pdesc
);
258 char *signals
= get_defined_signals(pdesc
);
260 pr_warn("No function %s found on pin %s (%d). Found signal(s) %s for function(s) %s\n",
261 pfunc
->name
, pdesc
->name
, pin
, signals
,
269 ret
= aspeed_sig_expr_enable(&pdata
->pinmux
, expr
);
277 static bool aspeed_expr_is_gpio(const struct aspeed_sig_expr
*expr
)
280 * The signal type is GPIO if the signal name has "GPIO" as a prefix.
281 * strncmp (rather than strcmp) is used to implement the prefix
284 * expr->signal might look like "GPIOT3" in the GPIO case.
286 return strncmp(expr
->signal
, "GPIO", 4) == 0;
289 static bool aspeed_gpio_in_exprs(const struct aspeed_sig_expr
**exprs
)
295 if (aspeed_expr_is_gpio(*exprs
))
303 int aspeed_gpio_request_enable(struct pinctrl_dev
*pctldev
,
304 struct pinctrl_gpio_range
*range
,
308 struct aspeed_pinctrl_data
*pdata
= pinctrl_dev_get_drvdata(pctldev
);
309 const struct aspeed_pin_desc
*pdesc
= pdata
->pins
[offset
].drv_data
;
310 const struct aspeed_sig_expr
***prios
, **funcs
, *expr
;
315 prios
= pdesc
->prios
;
320 /* Disable any functions of higher priority than GPIO */
321 while ((funcs
= *prios
)) {
322 if (aspeed_gpio_in_exprs(funcs
))
325 ret
= aspeed_disable_sig(&pdata
->pinmux
, funcs
);
333 char *signals
= get_defined_signals(pdesc
);
335 pr_warn("No GPIO signal type found on pin %s (%d). Found: %s\n",
336 pdesc
->name
, offset
, signals
);
345 * Disabling all higher-priority expressions is enough to enable the
346 * lowest-priority signal type. As such it has no associated
353 * If GPIO is not the lowest priority signal type, assume there is only
354 * one expression defined to enable the GPIO function
356 return aspeed_sig_expr_enable(&pdata
->pinmux
, expr
);
359 int aspeed_pinctrl_probe(struct platform_device
*pdev
,
360 struct pinctrl_desc
*pdesc
,
361 struct aspeed_pinctrl_data
*pdata
)
363 struct device
*parent
;
364 struct pinctrl_dev
*pctl
;
366 parent
= pdev
->dev
.parent
;
368 dev_err(&pdev
->dev
, "No parent for syscon pincontroller\n");
372 pdata
->scu
= syscon_node_to_regmap(parent
->of_node
);
373 if (IS_ERR(pdata
->scu
)) {
374 dev_err(&pdev
->dev
, "No regmap for syscon pincontroller parent\n");
375 return PTR_ERR(pdata
->scu
);
378 pdata
->pinmux
.maps
[ASPEED_IP_SCU
] = pdata
->scu
;
380 pctl
= pinctrl_register(pdesc
, &pdev
->dev
, pdata
);
383 dev_err(&pdev
->dev
, "Failed to register pinctrl\n");
384 return PTR_ERR(pctl
);
387 platform_set_drvdata(pdev
, pdata
);
392 static inline bool pin_in_config_range(unsigned int offset
,
393 const struct aspeed_pin_config
*config
)
395 return offset
>= config
->pins
[0] && offset
<= config
->pins
[1];
398 static inline const struct aspeed_pin_config
*find_pinconf_config(
399 const struct aspeed_pinctrl_data
*pdata
,
401 enum pin_config_param param
)
405 for (i
= 0; i
< pdata
->nconfigs
; i
++) {
406 if (param
== pdata
->configs
[i
].param
&&
407 pin_in_config_range(offset
, &pdata
->configs
[i
]))
408 return &pdata
->configs
[i
];
414 enum aspeed_pin_config_map_type
{ MAP_TYPE_ARG
, MAP_TYPE_VAL
};
416 static const struct aspeed_pin_config_map
*find_pinconf_map(
417 const struct aspeed_pinctrl_data
*pdata
,
418 enum pin_config_param param
,
419 enum aspeed_pin_config_map_type type
,
424 for (i
= 0; i
< pdata
->nconfmaps
; i
++) {
425 const struct aspeed_pin_config_map
*elem
;
428 elem
= &pdata
->confmaps
[i
];
432 match
= (elem
->arg
== -1 || elem
->arg
== value
);
435 match
= (elem
->val
== value
);
439 if (param
== elem
->param
&& match
)
446 int aspeed_pin_config_get(struct pinctrl_dev
*pctldev
, unsigned int offset
,
447 unsigned long *config
)
449 const enum pin_config_param param
= pinconf_to_config_param(*config
);
450 const struct aspeed_pin_config_map
*pmap
;
451 const struct aspeed_pinctrl_data
*pdata
;
452 const struct aspeed_pin_config
*pconf
;
457 pdata
= pinctrl_dev_get_drvdata(pctldev
);
458 pconf
= find_pinconf_config(pdata
, offset
, param
);
462 rc
= regmap_read(pdata
->scu
, pconf
->reg
, &val
);
466 pmap
= find_pinconf_map(pdata
, param
, MAP_TYPE_VAL
,
467 (val
& pconf
->mask
) >> __ffs(pconf
->mask
));
472 if (param
== PIN_CONFIG_DRIVE_STRENGTH
)
473 arg
= (u32
) pmap
->arg
;
474 else if (param
== PIN_CONFIG_BIAS_PULL_DOWN
)
482 *config
= pinconf_to_config_packed(param
, arg
);
487 int aspeed_pin_config_set(struct pinctrl_dev
*pctldev
, unsigned int offset
,
488 unsigned long *configs
, unsigned int num_configs
)
490 const struct aspeed_pinctrl_data
*pdata
;
494 pdata
= pinctrl_dev_get_drvdata(pctldev
);
496 for (i
= 0; i
< num_configs
; i
++) {
497 const struct aspeed_pin_config_map
*pmap
;
498 const struct aspeed_pin_config
*pconf
;
499 enum pin_config_param param
;
503 param
= pinconf_to_config_param(configs
[i
]);
504 arg
= pinconf_to_config_argument(configs
[i
]);
506 pconf
= find_pinconf_config(pdata
, offset
, param
);
510 pmap
= find_pinconf_map(pdata
, param
, MAP_TYPE_ARG
, arg
);
515 val
= pmap
->val
<< __ffs(pconf
->mask
);
517 rc
= regmap_update_bits(pdata
->scu
, pconf
->reg
,
523 pr_debug("%s: Set SCU%02X[%lu]=%d for param %d(=%d) on pin %d\n",
524 __func__
, pconf
->reg
, __ffs(pconf
->mask
),
525 pmap
->val
, param
, arg
, offset
);
531 int aspeed_pin_config_group_get(struct pinctrl_dev
*pctldev
,
532 unsigned int selector
,
533 unsigned long *config
)
535 const unsigned int *pins
;
539 rc
= aspeed_pinctrl_get_group_pins(pctldev
, selector
, &pins
, &npins
);
546 rc
= aspeed_pin_config_get(pctldev
, pins
[0], config
);
551 int aspeed_pin_config_group_set(struct pinctrl_dev
*pctldev
,
552 unsigned int selector
,
553 unsigned long *configs
,
554 unsigned int num_configs
)
556 const unsigned int *pins
;
561 pr_debug("%s: Fetching pins for group selector %d\n",
563 rc
= aspeed_pinctrl_get_group_pins(pctldev
, selector
, &pins
, &npins
);
567 for (i
= 0; i
< npins
; i
++) {
568 rc
= aspeed_pin_config_set(pctldev
, pins
[i
], configs
,