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