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