1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2016 IBM Corp.
4  */
5 
6 #include <linux/mfd/syscon.h>
7 #include <linux/platform_device.h>
8 #include <linux/seq_file.h>
9 #include <linux/slab.h>
10 #include <linux/string.h>
11 #include "../core.h"
12 #include "pinctrl-aspeed.h"
13 
aspeed_pinctrl_get_groups_count(struct pinctrl_dev * pctldev)14 int aspeed_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
15 {
16 	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
17 
18 	return pdata->pinmux.ngroups;
19 }
20 
aspeed_pinctrl_get_group_name(struct pinctrl_dev * pctldev,unsigned int group)21 const char *aspeed_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
22 		unsigned int group)
23 {
24 	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
25 
26 	return pdata->pinmux.groups[group].name;
27 }
28 
aspeed_pinctrl_get_group_pins(struct pinctrl_dev * pctldev,unsigned int group,const unsigned int ** pins,unsigned int * npins)29 int aspeed_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
30 				  unsigned int group, const unsigned int **pins,
31 				  unsigned int *npins)
32 {
33 	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
34 
35 	*pins = &pdata->pinmux.groups[group].pins[0];
36 	*npins = pdata->pinmux.groups[group].npins;
37 
38 	return 0;
39 }
40 
aspeed_pinctrl_pin_dbg_show(struct pinctrl_dev * pctldev,struct seq_file * s,unsigned int offset)41 void aspeed_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
42 				 struct seq_file *s, unsigned int offset)
43 {
44 	seq_printf(s, " %s", dev_name(pctldev->dev));
45 }
46 
aspeed_pinmux_get_fn_count(struct pinctrl_dev * pctldev)47 int aspeed_pinmux_get_fn_count(struct pinctrl_dev *pctldev)
48 {
49 	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
50 
51 	return pdata->pinmux.nfunctions;
52 }
53 
aspeed_pinmux_get_fn_name(struct pinctrl_dev * pctldev,unsigned int function)54 const char *aspeed_pinmux_get_fn_name(struct pinctrl_dev *pctldev,
55 				      unsigned int function)
56 {
57 	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
58 
59 	return pdata->pinmux.functions[function].name;
60 }
61 
aspeed_pinmux_get_fn_groups(struct pinctrl_dev * pctldev,unsigned int function,const char * const ** groups,unsigned int * const num_groups)62 int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
63 				unsigned int function,
64 				const char * const **groups,
65 				unsigned int * const num_groups)
66 {
67 	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
68 
69 	*groups = pdata->pinmux.functions[function].groups;
70 	*num_groups = pdata->pinmux.functions[function].ngroups;
71 
72 	return 0;
73 }
74 
aspeed_sig_expr_enable(struct aspeed_pinmux_data * ctx,const struct aspeed_sig_expr * expr)75 static int aspeed_sig_expr_enable(struct aspeed_pinmux_data *ctx,
76 				  const struct aspeed_sig_expr *expr)
77 {
78 	int ret;
79 
80 	pr_debug("Enabling signal %s for %s\n", expr->signal,
81 		 expr->function);
82 
83 	ret = aspeed_sig_expr_eval(ctx, expr, true);
84 	if (ret < 0)
85 		return ret;
86 
87 	if (!ret)
88 		return aspeed_sig_expr_set(ctx, expr, true);
89 
90 	return 0;
91 }
92 
aspeed_sig_expr_disable(struct aspeed_pinmux_data * ctx,const struct aspeed_sig_expr * expr)93 static int aspeed_sig_expr_disable(struct aspeed_pinmux_data *ctx,
94 				   const struct aspeed_sig_expr *expr)
95 {
96 	int ret;
97 
98 	pr_debug("Disabling signal %s for %s\n", expr->signal,
99 		 expr->function);
100 
101 	ret = aspeed_sig_expr_eval(ctx, expr, true);
102 	if (ret < 0)
103 		return ret;
104 
105 	if (ret)
106 		return aspeed_sig_expr_set(ctx, expr, false);
107 
108 	return 0;
109 }
110 
111 /**
112  * aspeed_disable_sig() - Disable a signal on a pin by disabling all provided
113  * signal expressions.
114  *
115  * @ctx: The pinmux context
116  * @exprs: The list of signal expressions (from a priority level on a pin)
117  *
118  * Return: 0 if all expressions are disabled, otherwise a negative error code
119  */
aspeed_disable_sig(struct aspeed_pinmux_data * ctx,const struct aspeed_sig_expr ** exprs)120 static int aspeed_disable_sig(struct aspeed_pinmux_data *ctx,
121 			      const struct aspeed_sig_expr **exprs)
122 {
123 	int ret = 0;
124 
125 	if (!exprs)
126 		return -EINVAL;
127 
128 	while (*exprs && !ret) {
129 		ret = aspeed_sig_expr_disable(ctx, *exprs);
130 		exprs++;
131 	}
132 
133 	return ret;
134 }
135 
136 /**
137  * aspeed_find_expr_by_name - Search for the signal expression needed to
138  * enable the pin's signal for the requested function.
139  *
140  * @exprs: List of signal expressions (haystack)
141  * @name: The name of the requested function (needle)
142  *
143  * Return: A pointer to the signal expression whose function tag matches the
144  * provided name, otherwise NULL.
145  *
146  */
aspeed_find_expr_by_name(const struct aspeed_sig_expr ** exprs,const char * name)147 static const struct aspeed_sig_expr *aspeed_find_expr_by_name(
148 		const struct aspeed_sig_expr **exprs, const char *name)
149 {
150 	while (*exprs) {
151 		if (strcmp((*exprs)->function, name) == 0)
152 			return *exprs;
153 		exprs++;
154 	}
155 
156 	return NULL;
157 }
158 
get_defined_attribute(const struct aspeed_pin_desc * pdesc,const char * (* get)(const struct aspeed_sig_expr *))159 static char *get_defined_attribute(const struct aspeed_pin_desc *pdesc,
160 				   const char *(*get)(
161 					   const struct aspeed_sig_expr *))
162 {
163 	char *found = NULL;
164 	size_t len = 0;
165 	const struct aspeed_sig_expr ***prios, **funcs, *expr;
166 
167 	prios = pdesc->prios;
168 
169 	while ((funcs = *prios)) {
170 		while ((expr = *funcs)) {
171 			const char *str = get(expr);
172 			size_t delta = strlen(str) + 2;
173 			char *expanded;
174 
175 			expanded = krealloc(found, len + delta + 1, GFP_KERNEL);
176 			if (!expanded) {
177 				kfree(found);
178 				return expanded;
179 			}
180 
181 			found = expanded;
182 			found[len] = '\0';
183 			len += delta;
184 
185 			strcat(found, str);
186 			strcat(found, ", ");
187 
188 			funcs++;
189 		}
190 		prios++;
191 	}
192 
193 	if (len < 2) {
194 		kfree(found);
195 		return NULL;
196 	}
197 
198 	found[len - 2] = '\0';
199 
200 	return found;
201 }
202 
aspeed_sig_expr_function(const struct aspeed_sig_expr * expr)203 static const char *aspeed_sig_expr_function(const struct aspeed_sig_expr *expr)
204 {
205 	return expr->function;
206 }
207 
get_defined_functions(const struct aspeed_pin_desc * pdesc)208 static char *get_defined_functions(const struct aspeed_pin_desc *pdesc)
209 {
210 	return get_defined_attribute(pdesc, aspeed_sig_expr_function);
211 }
212 
aspeed_sig_expr_signal(const struct aspeed_sig_expr * expr)213 static const char *aspeed_sig_expr_signal(const struct aspeed_sig_expr *expr)
214 {
215 	return expr->signal;
216 }
217 
get_defined_signals(const struct aspeed_pin_desc * pdesc)218 static char *get_defined_signals(const struct aspeed_pin_desc *pdesc)
219 {
220 	return get_defined_attribute(pdesc, aspeed_sig_expr_signal);
221 }
222 
aspeed_pinmux_set_mux(struct pinctrl_dev * pctldev,unsigned int function,unsigned int group)223 int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
224 			  unsigned int group)
225 {
226 	int i;
227 	int ret;
228 	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
229 	const struct aspeed_pin_group *pgroup = &pdata->pinmux.groups[group];
230 	const struct aspeed_pin_function *pfunc =
231 		&pdata->pinmux.functions[function];
232 
233 	for (i = 0; i < pgroup->npins; i++) {
234 		int pin = pgroup->pins[i];
235 		const struct aspeed_pin_desc *pdesc = pdata->pins[pin].drv_data;
236 		const struct aspeed_sig_expr *expr = NULL;
237 		const struct aspeed_sig_expr **funcs;
238 		const struct aspeed_sig_expr ***prios;
239 
240 		if (!pdesc)
241 			return -EINVAL;
242 
243 		pr_debug("Muxing pin %s for %s\n", pdesc->name, pfunc->name);
244 
245 		prios = pdesc->prios;
246 
247 		if (!prios)
248 			continue;
249 
250 		/* Disable functions at a higher priority than that requested */
251 		while ((funcs = *prios)) {
252 			expr = aspeed_find_expr_by_name(funcs, pfunc->name);
253 
254 			if (expr)
255 				break;
256 
257 			ret = aspeed_disable_sig(&pdata->pinmux, funcs);
258 			if (ret)
259 				return ret;
260 
261 			prios++;
262 		}
263 
264 		if (!expr) {
265 			char *functions = get_defined_functions(pdesc);
266 			char *signals = get_defined_signals(pdesc);
267 
268 			pr_warn("No function %s found on pin %s (%d). Found signal(s) %s for function(s) %s\n",
269 				pfunc->name, pdesc->name, pin, signals,
270 				functions);
271 			kfree(signals);
272 			kfree(functions);
273 
274 			return -ENXIO;
275 		}
276 
277 		ret = aspeed_sig_expr_enable(&pdata->pinmux, expr);
278 		if (ret)
279 			return ret;
280 
281 		pr_debug("Muxed pin %s as %s for %s\n", pdesc->name, expr->signal,
282 			 expr->function);
283 	}
284 
285 	return 0;
286 }
287 
aspeed_expr_is_gpio(const struct aspeed_sig_expr * expr)288 static bool aspeed_expr_is_gpio(const struct aspeed_sig_expr *expr)
289 {
290 	/*
291 	 * We need to differentiate between GPIO and non-GPIO signals to
292 	 * implement the gpio_request_enable() interface. For better or worse
293 	 * the ASPEED pinctrl driver uses the expression names to determine
294 	 * whether an expression will mux a pin for GPIO.
295 	 *
296 	 * Generally we have the following - A GPIO such as B1 has:
297 	 *
298 	 *    - expr->signal set to "GPIOB1"
299 	 *    - expr->function set to "GPIOB1"
300 	 *
301 	 * Using this fact we can determine whether the provided expression is
302 	 * a GPIO expression by testing the signal name for the string prefix
303 	 * "GPIO".
304 	 *
305 	 * However, some GPIOs are input-only, and the ASPEED datasheets name
306 	 * them differently. An input-only GPIO such as T0 has:
307 	 *
308 	 *    - expr->signal set to "GPIT0"
309 	 *    - expr->function set to "GPIT0"
310 	 *
311 	 * It's tempting to generalise the prefix test from "GPIO" to "GPI" to
312 	 * account for both GPIOs and GPIs, but in doing so we run aground on
313 	 * another feature:
314 	 *
315 	 * Some pins in the ASPEED BMC SoCs have a "pass-through" GPIO
316 	 * function where the input state of one pin is replicated as the
317 	 * output state of another (as if they were shorted together - a mux
318 	 * configuration that is typically enabled by hardware strapping).
319 	 * This feature allows the BMC to pass e.g. power button state through
320 	 * to the host while the BMC is yet to boot, but take control of the
321 	 * button state once the BMC has booted by muxing each pin as a
322 	 * separate, pin-specific GPIO.
323 	 *
324 	 * Conceptually this pass-through mode is a form of GPIO and is named
325 	 * as such in the datasheets, e.g. "GPID0". This naming similarity
326 	 * trips us up with the simple GPI-prefixed-signal-name scheme
327 	 * discussed above, as the pass-through configuration is not what we
328 	 * want when muxing a pin as GPIO for the GPIO subsystem.
329 	 *
330 	 * On e.g. the AST2400, a pass-through function "GPID0" is grouped on
331 	 * balls A18 and D16, where we have:
332 	 *
333 	 *    For ball A18:
334 	 *    - expr->signal set to "GPID0IN"
335 	 *    - expr->function set to "GPID0"
336 	 *
337 	 *    For ball D16:
338 	 *    - expr->signal set to "GPID0OUT"
339 	 *    - expr->function set to "GPID0"
340 	 *
341 	 * By contrast, the pin-specific GPIO expressions for the same pins are
342 	 * as follows:
343 	 *
344 	 *    For ball A18:
345 	 *    - expr->signal looks like "GPIOD0"
346 	 *    - expr->function looks like "GPIOD0"
347 	 *
348 	 *    For ball D16:
349 	 *    - expr->signal looks like "GPIOD1"
350 	 *    - expr->function looks like "GPIOD1"
351 	 *
352 	 * Testing both the signal _and_ function names gives us the means
353 	 * differentiate the pass-through GPIO pinmux configuration from the
354 	 * pin-specific configuration that the GPIO subsystem is after: An
355 	 * expression is a pin-specific (non-pass-through) GPIO configuration
356 	 * if the signal prefix is "GPI" and the signal name matches the
357 	 * function name.
358 	 */
359 	return !strncmp(expr->signal, "GPI", 3) &&
360 			!strcmp(expr->signal, expr->function);
361 }
362 
aspeed_gpio_in_exprs(const struct aspeed_sig_expr ** exprs)363 static bool aspeed_gpio_in_exprs(const struct aspeed_sig_expr **exprs)
364 {
365 	if (!exprs)
366 		return false;
367 
368 	while (*exprs) {
369 		if (aspeed_expr_is_gpio(*exprs))
370 			return true;
371 		exprs++;
372 	}
373 
374 	return false;
375 }
376 
aspeed_gpio_request_enable(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned int offset)377 int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
378 			       struct pinctrl_gpio_range *range,
379 			       unsigned int offset)
380 {
381 	int ret;
382 	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
383 	const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data;
384 	const struct aspeed_sig_expr ***prios, **funcs, *expr;
385 
386 	if (!pdesc)
387 		return -EINVAL;
388 
389 	prios = pdesc->prios;
390 
391 	if (!prios)
392 		return -ENXIO;
393 
394 	pr_debug("Muxing pin %s for GPIO\n", pdesc->name);
395 
396 	/* Disable any functions of higher priority than GPIO */
397 	while ((funcs = *prios)) {
398 		if (aspeed_gpio_in_exprs(funcs))
399 			break;
400 
401 		ret = aspeed_disable_sig(&pdata->pinmux, funcs);
402 		if (ret)
403 			return ret;
404 
405 		prios++;
406 	}
407 
408 	if (!funcs) {
409 		char *signals = get_defined_signals(pdesc);
410 
411 		pr_warn("No GPIO signal type found on pin %s (%d). Found: %s\n",
412 			pdesc->name, offset, signals);
413 		kfree(signals);
414 
415 		return -ENXIO;
416 	}
417 
418 	expr = *funcs;
419 
420 	/*
421 	 * Disabling all higher-priority expressions is enough to enable the
422 	 * lowest-priority signal type. As such it has no associated
423 	 * expression.
424 	 */
425 	if (!expr) {
426 		pr_debug("Muxed pin %s as GPIO\n", pdesc->name);
427 		return 0;
428 	}
429 
430 	/*
431 	 * If GPIO is not the lowest priority signal type, assume there is only
432 	 * one expression defined to enable the GPIO function
433 	 */
434 	ret = aspeed_sig_expr_enable(&pdata->pinmux, expr);
435 	if (ret)
436 		return ret;
437 
438 	pr_debug("Muxed pin %s as %s\n", pdesc->name, expr->signal);
439 
440 	return 0;
441 }
442 
aspeed_pinctrl_probe(struct platform_device * pdev,struct pinctrl_desc * pdesc,struct aspeed_pinctrl_data * pdata)443 int aspeed_pinctrl_probe(struct platform_device *pdev,
444 			 struct pinctrl_desc *pdesc,
445 			 struct aspeed_pinctrl_data *pdata)
446 {
447 	struct device *parent;
448 	struct pinctrl_dev *pctl;
449 
450 	parent = pdev->dev.parent;
451 	if (!parent) {
452 		dev_err(&pdev->dev, "No parent for syscon pincontroller\n");
453 		return -ENODEV;
454 	}
455 
456 	pdata->scu = syscon_node_to_regmap(parent->of_node);
457 	if (IS_ERR(pdata->scu)) {
458 		dev_err(&pdev->dev, "No regmap for syscon pincontroller parent\n");
459 		return PTR_ERR(pdata->scu);
460 	}
461 
462 	pdata->pinmux.maps[ASPEED_IP_SCU] = pdata->scu;
463 
464 	pctl = pinctrl_register(pdesc, &pdev->dev, pdata);
465 
466 	if (IS_ERR(pctl)) {
467 		dev_err(&pdev->dev, "Failed to register pinctrl\n");
468 		return PTR_ERR(pctl);
469 	}
470 
471 	platform_set_drvdata(pdev, pdata);
472 
473 	return 0;
474 }
475 
pin_in_config_range(unsigned int offset,const struct aspeed_pin_config * config)476 static inline bool pin_in_config_range(unsigned int offset,
477 		const struct aspeed_pin_config *config)
478 {
479 	return offset >= config->pins[0] && offset <= config->pins[1];
480 }
481 
find_pinconf_config(const struct aspeed_pinctrl_data * pdata,unsigned int offset,enum pin_config_param param)482 static inline const struct aspeed_pin_config *find_pinconf_config(
483 		const struct aspeed_pinctrl_data *pdata,
484 		unsigned int offset,
485 		enum pin_config_param param)
486 {
487 	unsigned int i;
488 
489 	for (i = 0; i < pdata->nconfigs; i++) {
490 		if (param == pdata->configs[i].param &&
491 				pin_in_config_range(offset, &pdata->configs[i]))
492 			return &pdata->configs[i];
493 	}
494 
495 	return NULL;
496 }
497 
498 enum aspeed_pin_config_map_type { MAP_TYPE_ARG, MAP_TYPE_VAL };
499 
find_pinconf_map(const struct aspeed_pinctrl_data * pdata,enum pin_config_param param,enum aspeed_pin_config_map_type type,s64 value)500 static const struct aspeed_pin_config_map *find_pinconf_map(
501 		const struct aspeed_pinctrl_data *pdata,
502 		enum pin_config_param param,
503 		enum aspeed_pin_config_map_type type,
504 		s64 value)
505 {
506 	int i;
507 
508 	for (i = 0; i < pdata->nconfmaps; i++) {
509 		const struct aspeed_pin_config_map *elem;
510 		bool match;
511 
512 		elem = &pdata->confmaps[i];
513 
514 		switch (type) {
515 		case MAP_TYPE_ARG:
516 			match = (elem->arg == -1 || elem->arg == value);
517 			break;
518 		case MAP_TYPE_VAL:
519 			match = (elem->val == value);
520 			break;
521 		}
522 
523 		if (param == elem->param && match)
524 			return elem;
525 	}
526 
527 	return NULL;
528 }
529 
aspeed_pin_config_get(struct pinctrl_dev * pctldev,unsigned int offset,unsigned long * config)530 int aspeed_pin_config_get(struct pinctrl_dev *pctldev, unsigned int offset,
531 		unsigned long *config)
532 {
533 	const enum pin_config_param param = pinconf_to_config_param(*config);
534 	const struct aspeed_pin_config_map *pmap;
535 	const struct aspeed_pinctrl_data *pdata;
536 	const struct aspeed_pin_config *pconf;
537 	unsigned int val;
538 	int rc = 0;
539 	u32 arg;
540 
541 	pdata = pinctrl_dev_get_drvdata(pctldev);
542 	pconf = find_pinconf_config(pdata, offset, param);
543 	if (!pconf)
544 		return -ENOTSUPP;
545 
546 	rc = regmap_read(pdata->scu, pconf->reg, &val);
547 	if (rc < 0)
548 		return rc;
549 
550 	pmap = find_pinconf_map(pdata, param, MAP_TYPE_VAL,
551 			(val & pconf->mask) >> __ffs(pconf->mask));
552 
553 	if (!pmap)
554 		return -EINVAL;
555 
556 	if (param == PIN_CONFIG_DRIVE_STRENGTH)
557 		arg = (u32) pmap->arg;
558 	else if (param == PIN_CONFIG_BIAS_PULL_DOWN)
559 		arg = !!pmap->arg;
560 	else
561 		arg = 1;
562 
563 	if (!arg)
564 		return -EINVAL;
565 
566 	*config = pinconf_to_config_packed(param, arg);
567 
568 	return 0;
569 }
570 
aspeed_pin_config_set(struct pinctrl_dev * pctldev,unsigned int offset,unsigned long * configs,unsigned int num_configs)571 int aspeed_pin_config_set(struct pinctrl_dev *pctldev, unsigned int offset,
572 		unsigned long *configs, unsigned int num_configs)
573 {
574 	const struct aspeed_pinctrl_data *pdata;
575 	unsigned int i;
576 	int rc = 0;
577 
578 	pdata = pinctrl_dev_get_drvdata(pctldev);
579 
580 	for (i = 0; i < num_configs; i++) {
581 		const struct aspeed_pin_config_map *pmap;
582 		const struct aspeed_pin_config *pconf;
583 		enum pin_config_param param;
584 		unsigned int val;
585 		u32 arg;
586 
587 		param = pinconf_to_config_param(configs[i]);
588 		arg = pinconf_to_config_argument(configs[i]);
589 
590 		pconf = find_pinconf_config(pdata, offset, param);
591 		if (!pconf)
592 			return -ENOTSUPP;
593 
594 		pmap = find_pinconf_map(pdata, param, MAP_TYPE_ARG, arg);
595 
596 		if (WARN_ON(!pmap))
597 			return -EINVAL;
598 
599 		val = pmap->val << __ffs(pconf->mask);
600 
601 		rc = regmap_update_bits(pdata->scu, pconf->reg,
602 					pconf->mask, val);
603 
604 		if (rc < 0)
605 			return rc;
606 
607 		pr_debug("%s: Set SCU%02X[0x%08X]=0x%X for param %d(=%d) on pin %d\n",
608 				__func__, pconf->reg, pconf->mask,
609 				val, param, arg, offset);
610 	}
611 
612 	return 0;
613 }
614 
aspeed_pin_config_group_get(struct pinctrl_dev * pctldev,unsigned int selector,unsigned long * config)615 int aspeed_pin_config_group_get(struct pinctrl_dev *pctldev,
616 		unsigned int selector,
617 		unsigned long *config)
618 {
619 	const unsigned int *pins;
620 	unsigned int npins;
621 	int rc;
622 
623 	rc = aspeed_pinctrl_get_group_pins(pctldev, selector, &pins, &npins);
624 	if (rc < 0)
625 		return rc;
626 
627 	if (!npins)
628 		return -ENODEV;
629 
630 	rc = aspeed_pin_config_get(pctldev, pins[0], config);
631 
632 	return rc;
633 }
634 
aspeed_pin_config_group_set(struct pinctrl_dev * pctldev,unsigned int selector,unsigned long * configs,unsigned int num_configs)635 int aspeed_pin_config_group_set(struct pinctrl_dev *pctldev,
636 		unsigned int selector,
637 		unsigned long *configs,
638 		unsigned int num_configs)
639 {
640 	const unsigned int *pins;
641 	unsigned int npins;
642 	int rc;
643 	int i;
644 
645 	pr_debug("%s: Fetching pins for group selector %d\n",
646 			__func__, selector);
647 	rc = aspeed_pinctrl_get_group_pins(pctldev, selector, &pins, &npins);
648 	if (rc < 0)
649 		return rc;
650 
651 	for (i = 0; i < npins; i++) {
652 		rc = aspeed_pin_config_set(pctldev, pins[i], configs,
653 				num_configs);
654 		if (rc < 0)
655 			return rc;
656 	}
657 
658 	return 0;
659 }
660