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