1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Allwinner A1X SoCs pinctrl driver.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2012 Maxime Ripard
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Maxime Ripard <maxime.ripard@free-electrons.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * This file is licensed under the terms of the GNU General Public
9*4882a593Smuzhiyun * License version 2. This program is licensed "as is" without any
10*4882a593Smuzhiyun * warranty of any kind, whether express or implied.
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun #include <linux/clk.h>
15*4882a593Smuzhiyun #include <linux/gpio/driver.h>
16*4882a593Smuzhiyun #include <linux/interrupt.h>
17*4882a593Smuzhiyun #include <linux/irqdomain.h>
18*4882a593Smuzhiyun #include <linux/irqchip/chained_irq.h>
19*4882a593Smuzhiyun #include <linux/export.h>
20*4882a593Smuzhiyun #include <linux/of.h>
21*4882a593Smuzhiyun #include <linux/of_clk.h>
22*4882a593Smuzhiyun #include <linux/of_address.h>
23*4882a593Smuzhiyun #include <linux/of_device.h>
24*4882a593Smuzhiyun #include <linux/of_irq.h>
25*4882a593Smuzhiyun #include <linux/pinctrl/consumer.h>
26*4882a593Smuzhiyun #include <linux/pinctrl/machine.h>
27*4882a593Smuzhiyun #include <linux/pinctrl/pinctrl.h>
28*4882a593Smuzhiyun #include <linux/pinctrl/pinconf-generic.h>
29*4882a593Smuzhiyun #include <linux/pinctrl/pinmux.h>
30*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
31*4882a593Smuzhiyun #include <linux/platform_device.h>
32*4882a593Smuzhiyun #include <linux/slab.h>
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include <dt-bindings/pinctrl/sun4i-a10.h>
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #include "../core.h"
37*4882a593Smuzhiyun #include "pinctrl-sunxi.h"
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /*
40*4882a593Smuzhiyun * These lock classes tell lockdep that GPIO IRQs are in a different
41*4882a593Smuzhiyun * category than their parents, so it won't report false recursion.
42*4882a593Smuzhiyun */
43*4882a593Smuzhiyun static struct lock_class_key sunxi_pinctrl_irq_lock_class;
44*4882a593Smuzhiyun static struct lock_class_key sunxi_pinctrl_irq_request_class;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun static struct irq_chip sunxi_pinctrl_edge_irq_chip;
47*4882a593Smuzhiyun static struct irq_chip sunxi_pinctrl_level_irq_chip;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun static struct sunxi_pinctrl_group *
sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl * pctl,const char * group)50*4882a593Smuzhiyun sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun int i;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun for (i = 0; i < pctl->ngroups; i++) {
55*4882a593Smuzhiyun struct sunxi_pinctrl_group *grp = pctl->groups + i;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun if (!strcmp(grp->name, group))
58*4882a593Smuzhiyun return grp;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun return NULL;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun static struct sunxi_pinctrl_function *
sunxi_pinctrl_find_function_by_name(struct sunxi_pinctrl * pctl,const char * name)65*4882a593Smuzhiyun sunxi_pinctrl_find_function_by_name(struct sunxi_pinctrl *pctl,
66*4882a593Smuzhiyun const char *name)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun struct sunxi_pinctrl_function *func = pctl->functions;
69*4882a593Smuzhiyun int i;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun for (i = 0; i < pctl->nfunctions; i++) {
72*4882a593Smuzhiyun if (!func[i].name)
73*4882a593Smuzhiyun break;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun if (!strcmp(func[i].name, name))
76*4882a593Smuzhiyun return func + i;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun return NULL;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun static struct sunxi_desc_function *
sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl * pctl,const char * pin_name,const char * func_name)83*4882a593Smuzhiyun sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl,
84*4882a593Smuzhiyun const char *pin_name,
85*4882a593Smuzhiyun const char *func_name)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun int i;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun for (i = 0; i < pctl->desc->npins; i++) {
90*4882a593Smuzhiyun const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (!strcmp(pin->pin.name, pin_name)) {
93*4882a593Smuzhiyun struct sunxi_desc_function *func = pin->functions;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun while (func->name) {
96*4882a593Smuzhiyun if (!strcmp(func->name, func_name) &&
97*4882a593Smuzhiyun (!func->variant ||
98*4882a593Smuzhiyun func->variant & pctl->variant))
99*4882a593Smuzhiyun return func;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun func++;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun return NULL;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun static struct sunxi_desc_function *
sunxi_pinctrl_desc_find_function_by_pin(struct sunxi_pinctrl * pctl,const u16 pin_num,const char * func_name)110*4882a593Smuzhiyun sunxi_pinctrl_desc_find_function_by_pin(struct sunxi_pinctrl *pctl,
111*4882a593Smuzhiyun const u16 pin_num,
112*4882a593Smuzhiyun const char *func_name)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun int i;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun for (i = 0; i < pctl->desc->npins; i++) {
117*4882a593Smuzhiyun const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun if (pin->pin.number == pin_num) {
120*4882a593Smuzhiyun struct sunxi_desc_function *func = pin->functions;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun while (func->name) {
123*4882a593Smuzhiyun if (!strcmp(func->name, func_name))
124*4882a593Smuzhiyun return func;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun func++;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun return NULL;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
sunxi_pctrl_get_groups_count(struct pinctrl_dev * pctldev)134*4882a593Smuzhiyun static int sunxi_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun return pctl->ngroups;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
sunxi_pctrl_get_group_name(struct pinctrl_dev * pctldev,unsigned group)141*4882a593Smuzhiyun static const char *sunxi_pctrl_get_group_name(struct pinctrl_dev *pctldev,
142*4882a593Smuzhiyun unsigned group)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun return pctl->groups[group].name;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
sunxi_pctrl_get_group_pins(struct pinctrl_dev * pctldev,unsigned group,const unsigned ** pins,unsigned * num_pins)149*4882a593Smuzhiyun static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
150*4882a593Smuzhiyun unsigned group,
151*4882a593Smuzhiyun const unsigned **pins,
152*4882a593Smuzhiyun unsigned *num_pins)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun *pins = (unsigned *)&pctl->groups[group].pin;
157*4882a593Smuzhiyun *num_pins = 1;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun return 0;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
sunxi_pctrl_has_bias_prop(struct device_node * node)162*4882a593Smuzhiyun static bool sunxi_pctrl_has_bias_prop(struct device_node *node)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun return of_find_property(node, "bias-pull-up", NULL) ||
165*4882a593Smuzhiyun of_find_property(node, "bias-pull-down", NULL) ||
166*4882a593Smuzhiyun of_find_property(node, "bias-disable", NULL) ||
167*4882a593Smuzhiyun of_find_property(node, "allwinner,pull", NULL);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
sunxi_pctrl_has_drive_prop(struct device_node * node)170*4882a593Smuzhiyun static bool sunxi_pctrl_has_drive_prop(struct device_node *node)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun return of_find_property(node, "drive-strength", NULL) ||
173*4882a593Smuzhiyun of_find_property(node, "allwinner,drive", NULL);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
sunxi_pctrl_parse_bias_prop(struct device_node * node)176*4882a593Smuzhiyun static int sunxi_pctrl_parse_bias_prop(struct device_node *node)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun u32 val;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun /* Try the new style binding */
181*4882a593Smuzhiyun if (of_find_property(node, "bias-pull-up", NULL))
182*4882a593Smuzhiyun return PIN_CONFIG_BIAS_PULL_UP;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun if (of_find_property(node, "bias-pull-down", NULL))
185*4882a593Smuzhiyun return PIN_CONFIG_BIAS_PULL_DOWN;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun if (of_find_property(node, "bias-disable", NULL))
188*4882a593Smuzhiyun return PIN_CONFIG_BIAS_DISABLE;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun /* And fall back to the old binding */
191*4882a593Smuzhiyun if (of_property_read_u32(node, "allwinner,pull", &val))
192*4882a593Smuzhiyun return -EINVAL;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun switch (val) {
195*4882a593Smuzhiyun case SUN4I_PINCTRL_NO_PULL:
196*4882a593Smuzhiyun return PIN_CONFIG_BIAS_DISABLE;
197*4882a593Smuzhiyun case SUN4I_PINCTRL_PULL_UP:
198*4882a593Smuzhiyun return PIN_CONFIG_BIAS_PULL_UP;
199*4882a593Smuzhiyun case SUN4I_PINCTRL_PULL_DOWN:
200*4882a593Smuzhiyun return PIN_CONFIG_BIAS_PULL_DOWN;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun return -EINVAL;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
sunxi_pctrl_parse_drive_prop(struct device_node * node)206*4882a593Smuzhiyun static int sunxi_pctrl_parse_drive_prop(struct device_node *node)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun u32 val;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* Try the new style binding */
211*4882a593Smuzhiyun if (!of_property_read_u32(node, "drive-strength", &val)) {
212*4882a593Smuzhiyun /* We can't go below 10mA ... */
213*4882a593Smuzhiyun if (val < 10)
214*4882a593Smuzhiyun return -EINVAL;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /* ... and only up to 40 mA ... */
217*4882a593Smuzhiyun if (val > 40)
218*4882a593Smuzhiyun val = 40;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun /* by steps of 10 mA */
221*4882a593Smuzhiyun return rounddown(val, 10);
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun /* And then fall back to the old binding */
225*4882a593Smuzhiyun if (of_property_read_u32(node, "allwinner,drive", &val))
226*4882a593Smuzhiyun return -EINVAL;
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun return (val + 1) * 10;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
sunxi_pctrl_parse_function_prop(struct device_node * node)231*4882a593Smuzhiyun static const char *sunxi_pctrl_parse_function_prop(struct device_node *node)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun const char *function;
234*4882a593Smuzhiyun int ret;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun /* Try the generic binding */
237*4882a593Smuzhiyun ret = of_property_read_string(node, "function", &function);
238*4882a593Smuzhiyun if (!ret)
239*4882a593Smuzhiyun return function;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun /* And fall back to our legacy one */
242*4882a593Smuzhiyun ret = of_property_read_string(node, "allwinner,function", &function);
243*4882a593Smuzhiyun if (!ret)
244*4882a593Smuzhiyun return function;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun return NULL;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
sunxi_pctrl_find_pins_prop(struct device_node * node,int * npins)249*4882a593Smuzhiyun static const char *sunxi_pctrl_find_pins_prop(struct device_node *node,
250*4882a593Smuzhiyun int *npins)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun int count;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun /* Try the generic binding */
255*4882a593Smuzhiyun count = of_property_count_strings(node, "pins");
256*4882a593Smuzhiyun if (count > 0) {
257*4882a593Smuzhiyun *npins = count;
258*4882a593Smuzhiyun return "pins";
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /* And fall back to our legacy one */
262*4882a593Smuzhiyun count = of_property_count_strings(node, "allwinner,pins");
263*4882a593Smuzhiyun if (count > 0) {
264*4882a593Smuzhiyun *npins = count;
265*4882a593Smuzhiyun return "allwinner,pins";
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun return NULL;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
sunxi_pctrl_build_pin_config(struct device_node * node,unsigned int * len)271*4882a593Smuzhiyun static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
272*4882a593Smuzhiyun unsigned int *len)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun unsigned long *pinconfig;
275*4882a593Smuzhiyun unsigned int configlen = 0, idx = 0;
276*4882a593Smuzhiyun int ret;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun if (sunxi_pctrl_has_drive_prop(node))
279*4882a593Smuzhiyun configlen++;
280*4882a593Smuzhiyun if (sunxi_pctrl_has_bias_prop(node))
281*4882a593Smuzhiyun configlen++;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun /*
284*4882a593Smuzhiyun * If we don't have any configuration, bail out
285*4882a593Smuzhiyun */
286*4882a593Smuzhiyun if (!configlen)
287*4882a593Smuzhiyun return NULL;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun pinconfig = kcalloc(configlen, sizeof(*pinconfig), GFP_KERNEL);
290*4882a593Smuzhiyun if (!pinconfig)
291*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun if (sunxi_pctrl_has_drive_prop(node)) {
294*4882a593Smuzhiyun int drive = sunxi_pctrl_parse_drive_prop(node);
295*4882a593Smuzhiyun if (drive < 0) {
296*4882a593Smuzhiyun ret = drive;
297*4882a593Smuzhiyun goto err_free;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH,
301*4882a593Smuzhiyun drive);
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (sunxi_pctrl_has_bias_prop(node)) {
305*4882a593Smuzhiyun int pull = sunxi_pctrl_parse_bias_prop(node);
306*4882a593Smuzhiyun int arg = 0;
307*4882a593Smuzhiyun if (pull < 0) {
308*4882a593Smuzhiyun ret = pull;
309*4882a593Smuzhiyun goto err_free;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun if (pull != PIN_CONFIG_BIAS_DISABLE)
313*4882a593Smuzhiyun arg = 1; /* hardware uses weak pull resistors */
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun pinconfig[idx++] = pinconf_to_config_packed(pull, arg);
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun *len = configlen;
320*4882a593Smuzhiyun return pinconfig;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun err_free:
323*4882a593Smuzhiyun kfree(pinconfig);
324*4882a593Smuzhiyun return ERR_PTR(ret);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
sunxi_pctrl_dt_node_to_map(struct pinctrl_dev * pctldev,struct device_node * node,struct pinctrl_map ** map,unsigned * num_maps)327*4882a593Smuzhiyun static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
328*4882a593Smuzhiyun struct device_node *node,
329*4882a593Smuzhiyun struct pinctrl_map **map,
330*4882a593Smuzhiyun unsigned *num_maps)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
333*4882a593Smuzhiyun unsigned long *pinconfig;
334*4882a593Smuzhiyun struct property *prop;
335*4882a593Smuzhiyun const char *function, *pin_prop;
336*4882a593Smuzhiyun const char *group;
337*4882a593Smuzhiyun int ret, npins, nmaps, configlen = 0, i = 0;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun *map = NULL;
340*4882a593Smuzhiyun *num_maps = 0;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun function = sunxi_pctrl_parse_function_prop(node);
343*4882a593Smuzhiyun if (!function) {
344*4882a593Smuzhiyun dev_err(pctl->dev, "missing function property in node %pOFn\n",
345*4882a593Smuzhiyun node);
346*4882a593Smuzhiyun return -EINVAL;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun pin_prop = sunxi_pctrl_find_pins_prop(node, &npins);
350*4882a593Smuzhiyun if (!pin_prop) {
351*4882a593Smuzhiyun dev_err(pctl->dev, "missing pins property in node %pOFn\n",
352*4882a593Smuzhiyun node);
353*4882a593Smuzhiyun return -EINVAL;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /*
357*4882a593Smuzhiyun * We have two maps for each pin: one for the function, one
358*4882a593Smuzhiyun * for the configuration (bias, strength, etc).
359*4882a593Smuzhiyun *
360*4882a593Smuzhiyun * We might be slightly overshooting, since we might not have
361*4882a593Smuzhiyun * any configuration.
362*4882a593Smuzhiyun */
363*4882a593Smuzhiyun nmaps = npins * 2;
364*4882a593Smuzhiyun *map = kmalloc_array(nmaps, sizeof(struct pinctrl_map), GFP_KERNEL);
365*4882a593Smuzhiyun if (!*map)
366*4882a593Smuzhiyun return -ENOMEM;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun pinconfig = sunxi_pctrl_build_pin_config(node, &configlen);
369*4882a593Smuzhiyun if (IS_ERR(pinconfig)) {
370*4882a593Smuzhiyun ret = PTR_ERR(pinconfig);
371*4882a593Smuzhiyun goto err_free_map;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun of_property_for_each_string(node, pin_prop, prop, group) {
375*4882a593Smuzhiyun struct sunxi_pinctrl_group *grp =
376*4882a593Smuzhiyun sunxi_pinctrl_find_group_by_name(pctl, group);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun if (!grp) {
379*4882a593Smuzhiyun dev_err(pctl->dev, "unknown pin %s", group);
380*4882a593Smuzhiyun continue;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (!sunxi_pinctrl_desc_find_function_by_name(pctl,
384*4882a593Smuzhiyun grp->name,
385*4882a593Smuzhiyun function)) {
386*4882a593Smuzhiyun dev_err(pctl->dev, "unsupported function %s on pin %s",
387*4882a593Smuzhiyun function, group);
388*4882a593Smuzhiyun continue;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun (*map)[i].type = PIN_MAP_TYPE_MUX_GROUP;
392*4882a593Smuzhiyun (*map)[i].data.mux.group = group;
393*4882a593Smuzhiyun (*map)[i].data.mux.function = function;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun i++;
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun if (pinconfig) {
398*4882a593Smuzhiyun (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
399*4882a593Smuzhiyun (*map)[i].data.configs.group_or_pin = group;
400*4882a593Smuzhiyun (*map)[i].data.configs.configs = pinconfig;
401*4882a593Smuzhiyun (*map)[i].data.configs.num_configs = configlen;
402*4882a593Smuzhiyun i++;
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun *num_maps = i;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun /*
409*4882a593Smuzhiyun * We know have the number of maps we need, we can resize our
410*4882a593Smuzhiyun * map array
411*4882a593Smuzhiyun */
412*4882a593Smuzhiyun *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL);
413*4882a593Smuzhiyun if (!*map)
414*4882a593Smuzhiyun return -ENOMEM;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun return 0;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun err_free_map:
419*4882a593Smuzhiyun kfree(*map);
420*4882a593Smuzhiyun *map = NULL;
421*4882a593Smuzhiyun return ret;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
sunxi_pctrl_dt_free_map(struct pinctrl_dev * pctldev,struct pinctrl_map * map,unsigned num_maps)424*4882a593Smuzhiyun static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
425*4882a593Smuzhiyun struct pinctrl_map *map,
426*4882a593Smuzhiyun unsigned num_maps)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun int i;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun /* pin config is never in the first map */
431*4882a593Smuzhiyun for (i = 1; i < num_maps; i++) {
432*4882a593Smuzhiyun if (map[i].type != PIN_MAP_TYPE_CONFIGS_GROUP)
433*4882a593Smuzhiyun continue;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun /*
436*4882a593Smuzhiyun * All the maps share the same pin config,
437*4882a593Smuzhiyun * free only the first one we find.
438*4882a593Smuzhiyun */
439*4882a593Smuzhiyun kfree(map[i].data.configs.configs);
440*4882a593Smuzhiyun break;
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun kfree(map);
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun static const struct pinctrl_ops sunxi_pctrl_ops = {
447*4882a593Smuzhiyun .dt_node_to_map = sunxi_pctrl_dt_node_to_map,
448*4882a593Smuzhiyun .dt_free_map = sunxi_pctrl_dt_free_map,
449*4882a593Smuzhiyun .get_groups_count = sunxi_pctrl_get_groups_count,
450*4882a593Smuzhiyun .get_group_name = sunxi_pctrl_get_group_name,
451*4882a593Smuzhiyun .get_group_pins = sunxi_pctrl_get_group_pins,
452*4882a593Smuzhiyun };
453*4882a593Smuzhiyun
sunxi_pconf_reg(unsigned pin,enum pin_config_param param,u32 * offset,u32 * shift,u32 * mask)454*4882a593Smuzhiyun static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param,
455*4882a593Smuzhiyun u32 *offset, u32 *shift, u32 *mask)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun switch (param) {
458*4882a593Smuzhiyun case PIN_CONFIG_DRIVE_STRENGTH:
459*4882a593Smuzhiyun *offset = sunxi_dlevel_reg(pin);
460*4882a593Smuzhiyun *shift = sunxi_dlevel_offset(pin);
461*4882a593Smuzhiyun *mask = DLEVEL_PINS_MASK;
462*4882a593Smuzhiyun break;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun case PIN_CONFIG_BIAS_PULL_UP:
465*4882a593Smuzhiyun case PIN_CONFIG_BIAS_PULL_DOWN:
466*4882a593Smuzhiyun case PIN_CONFIG_BIAS_DISABLE:
467*4882a593Smuzhiyun *offset = sunxi_pull_reg(pin);
468*4882a593Smuzhiyun *shift = sunxi_pull_offset(pin);
469*4882a593Smuzhiyun *mask = PULL_PINS_MASK;
470*4882a593Smuzhiyun break;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun default:
473*4882a593Smuzhiyun return -ENOTSUPP;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun return 0;
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
sunxi_pconf_get(struct pinctrl_dev * pctldev,unsigned pin,unsigned long * config)479*4882a593Smuzhiyun static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
480*4882a593Smuzhiyun unsigned long *config)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
483*4882a593Smuzhiyun enum pin_config_param param = pinconf_to_config_param(*config);
484*4882a593Smuzhiyun u32 offset, shift, mask, val;
485*4882a593Smuzhiyun u16 arg;
486*4882a593Smuzhiyun int ret;
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun pin -= pctl->desc->pin_base;
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
491*4882a593Smuzhiyun if (ret < 0)
492*4882a593Smuzhiyun return ret;
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun val = (readl(pctl->membase + offset) >> shift) & mask;
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun switch (pinconf_to_config_param(*config)) {
497*4882a593Smuzhiyun case PIN_CONFIG_DRIVE_STRENGTH:
498*4882a593Smuzhiyun arg = (val + 1) * 10;
499*4882a593Smuzhiyun break;
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun case PIN_CONFIG_BIAS_PULL_UP:
502*4882a593Smuzhiyun if (val != SUN4I_PINCTRL_PULL_UP)
503*4882a593Smuzhiyun return -EINVAL;
504*4882a593Smuzhiyun arg = 1; /* hardware is weak pull-up */
505*4882a593Smuzhiyun break;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun case PIN_CONFIG_BIAS_PULL_DOWN:
508*4882a593Smuzhiyun if (val != SUN4I_PINCTRL_PULL_DOWN)
509*4882a593Smuzhiyun return -EINVAL;
510*4882a593Smuzhiyun arg = 1; /* hardware is weak pull-down */
511*4882a593Smuzhiyun break;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun case PIN_CONFIG_BIAS_DISABLE:
514*4882a593Smuzhiyun if (val != SUN4I_PINCTRL_NO_PULL)
515*4882a593Smuzhiyun return -EINVAL;
516*4882a593Smuzhiyun arg = 0;
517*4882a593Smuzhiyun break;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun default:
520*4882a593Smuzhiyun /* sunxi_pconf_reg should catch anything unsupported */
521*4882a593Smuzhiyun WARN_ON(1);
522*4882a593Smuzhiyun return -ENOTSUPP;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun *config = pinconf_to_config_packed(param, arg);
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun return 0;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
sunxi_pconf_group_get(struct pinctrl_dev * pctldev,unsigned group,unsigned long * config)530*4882a593Smuzhiyun static int sunxi_pconf_group_get(struct pinctrl_dev *pctldev,
531*4882a593Smuzhiyun unsigned group,
532*4882a593Smuzhiyun unsigned long *config)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
535*4882a593Smuzhiyun struct sunxi_pinctrl_group *g = &pctl->groups[group];
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun /* We only support 1 pin per group. Chain it to the pin callback */
538*4882a593Smuzhiyun return sunxi_pconf_get(pctldev, g->pin, config);
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
sunxi_pconf_set(struct pinctrl_dev * pctldev,unsigned pin,unsigned long * configs,unsigned num_configs)541*4882a593Smuzhiyun static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
542*4882a593Smuzhiyun unsigned long *configs, unsigned num_configs)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
545*4882a593Smuzhiyun int i;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun pin -= pctl->desc->pin_base;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun for (i = 0; i < num_configs; i++) {
550*4882a593Smuzhiyun enum pin_config_param param;
551*4882a593Smuzhiyun unsigned long flags;
552*4882a593Smuzhiyun u32 offset, shift, mask, reg;
553*4882a593Smuzhiyun u32 arg, val;
554*4882a593Smuzhiyun int ret;
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun param = pinconf_to_config_param(configs[i]);
557*4882a593Smuzhiyun arg = pinconf_to_config_argument(configs[i]);
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
560*4882a593Smuzhiyun if (ret < 0)
561*4882a593Smuzhiyun return ret;
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun switch (param) {
564*4882a593Smuzhiyun case PIN_CONFIG_DRIVE_STRENGTH:
565*4882a593Smuzhiyun if (arg < 10 || arg > 40)
566*4882a593Smuzhiyun return -EINVAL;
567*4882a593Smuzhiyun /*
568*4882a593Smuzhiyun * We convert from mA to what the register expects:
569*4882a593Smuzhiyun * 0: 10mA
570*4882a593Smuzhiyun * 1: 20mA
571*4882a593Smuzhiyun * 2: 30mA
572*4882a593Smuzhiyun * 3: 40mA
573*4882a593Smuzhiyun */
574*4882a593Smuzhiyun val = arg / 10 - 1;
575*4882a593Smuzhiyun break;
576*4882a593Smuzhiyun case PIN_CONFIG_BIAS_DISABLE:
577*4882a593Smuzhiyun val = 0;
578*4882a593Smuzhiyun break;
579*4882a593Smuzhiyun case PIN_CONFIG_BIAS_PULL_UP:
580*4882a593Smuzhiyun if (arg == 0)
581*4882a593Smuzhiyun return -EINVAL;
582*4882a593Smuzhiyun val = 1;
583*4882a593Smuzhiyun break;
584*4882a593Smuzhiyun case PIN_CONFIG_BIAS_PULL_DOWN:
585*4882a593Smuzhiyun if (arg == 0)
586*4882a593Smuzhiyun return -EINVAL;
587*4882a593Smuzhiyun val = 2;
588*4882a593Smuzhiyun break;
589*4882a593Smuzhiyun default:
590*4882a593Smuzhiyun /* sunxi_pconf_reg should catch anything unsupported */
591*4882a593Smuzhiyun WARN_ON(1);
592*4882a593Smuzhiyun return -ENOTSUPP;
593*4882a593Smuzhiyun }
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun raw_spin_lock_irqsave(&pctl->lock, flags);
596*4882a593Smuzhiyun reg = readl(pctl->membase + offset);
597*4882a593Smuzhiyun reg &= ~(mask << shift);
598*4882a593Smuzhiyun writel(reg | val << shift, pctl->membase + offset);
599*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&pctl->lock, flags);
600*4882a593Smuzhiyun } /* for each config */
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun return 0;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
sunxi_pconf_group_set(struct pinctrl_dev * pctldev,unsigned group,unsigned long * configs,unsigned num_configs)605*4882a593Smuzhiyun static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
606*4882a593Smuzhiyun unsigned long *configs, unsigned num_configs)
607*4882a593Smuzhiyun {
608*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
609*4882a593Smuzhiyun struct sunxi_pinctrl_group *g = &pctl->groups[group];
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun /* We only support 1 pin per group. Chain it to the pin callback */
612*4882a593Smuzhiyun return sunxi_pconf_set(pctldev, g->pin, configs, num_configs);
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun static const struct pinconf_ops sunxi_pconf_ops = {
616*4882a593Smuzhiyun .is_generic = true,
617*4882a593Smuzhiyun .pin_config_get = sunxi_pconf_get,
618*4882a593Smuzhiyun .pin_config_set = sunxi_pconf_set,
619*4882a593Smuzhiyun .pin_config_group_get = sunxi_pconf_group_get,
620*4882a593Smuzhiyun .pin_config_group_set = sunxi_pconf_group_set,
621*4882a593Smuzhiyun };
622*4882a593Smuzhiyun
sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl * pctl,unsigned pin,struct regulator * supply)623*4882a593Smuzhiyun static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
624*4882a593Smuzhiyun unsigned pin,
625*4882a593Smuzhiyun struct regulator *supply)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun unsigned short bank;
628*4882a593Smuzhiyun unsigned long flags;
629*4882a593Smuzhiyun u32 val, reg;
630*4882a593Smuzhiyun int uV;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun if (!pctl->desc->io_bias_cfg_variant)
633*4882a593Smuzhiyun return 0;
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun uV = regulator_get_voltage(supply);
636*4882a593Smuzhiyun if (uV < 0)
637*4882a593Smuzhiyun return uV;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun /* Might be dummy regulator with no voltage set */
640*4882a593Smuzhiyun if (uV == 0)
641*4882a593Smuzhiyun return 0;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun pin -= pctl->desc->pin_base;
644*4882a593Smuzhiyun bank = pin / PINS_PER_BANK;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun switch (pctl->desc->io_bias_cfg_variant) {
647*4882a593Smuzhiyun case BIAS_VOLTAGE_GRP_CONFIG:
648*4882a593Smuzhiyun /*
649*4882a593Smuzhiyun * Configured value must be equal or greater to actual
650*4882a593Smuzhiyun * voltage.
651*4882a593Smuzhiyun */
652*4882a593Smuzhiyun if (uV <= 1800000)
653*4882a593Smuzhiyun val = 0x0; /* 1.8V */
654*4882a593Smuzhiyun else if (uV <= 2500000)
655*4882a593Smuzhiyun val = 0x6; /* 2.5V */
656*4882a593Smuzhiyun else if (uV <= 2800000)
657*4882a593Smuzhiyun val = 0x9; /* 2.8V */
658*4882a593Smuzhiyun else if (uV <= 3000000)
659*4882a593Smuzhiyun val = 0xA; /* 3.0V */
660*4882a593Smuzhiyun else
661*4882a593Smuzhiyun val = 0xD; /* 3.3V */
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun reg = readl(pctl->membase + sunxi_grp_config_reg(pin));
664*4882a593Smuzhiyun reg &= ~IO_BIAS_MASK;
665*4882a593Smuzhiyun writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin));
666*4882a593Smuzhiyun return 0;
667*4882a593Smuzhiyun case BIAS_VOLTAGE_PIO_POW_MODE_SEL:
668*4882a593Smuzhiyun val = uV <= 1800000 ? 1 : 0;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun raw_spin_lock_irqsave(&pctl->lock, flags);
671*4882a593Smuzhiyun reg = readl(pctl->membase + PIO_POW_MOD_SEL_REG);
672*4882a593Smuzhiyun reg &= ~(1 << bank);
673*4882a593Smuzhiyun writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG);
674*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&pctl->lock, flags);
675*4882a593Smuzhiyun return 0;
676*4882a593Smuzhiyun default:
677*4882a593Smuzhiyun return -EINVAL;
678*4882a593Smuzhiyun }
679*4882a593Smuzhiyun }
680*4882a593Smuzhiyun
sunxi_pmx_get_funcs_cnt(struct pinctrl_dev * pctldev)681*4882a593Smuzhiyun static int sunxi_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
682*4882a593Smuzhiyun {
683*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun return pctl->nfunctions;
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
sunxi_pmx_get_func_name(struct pinctrl_dev * pctldev,unsigned function)688*4882a593Smuzhiyun static const char *sunxi_pmx_get_func_name(struct pinctrl_dev *pctldev,
689*4882a593Smuzhiyun unsigned function)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun return pctl->functions[function].name;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
sunxi_pmx_get_func_groups(struct pinctrl_dev * pctldev,unsigned function,const char * const ** groups,unsigned * const num_groups)696*4882a593Smuzhiyun static int sunxi_pmx_get_func_groups(struct pinctrl_dev *pctldev,
697*4882a593Smuzhiyun unsigned function,
698*4882a593Smuzhiyun const char * const **groups,
699*4882a593Smuzhiyun unsigned * const num_groups)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun *groups = pctl->functions[function].groups;
704*4882a593Smuzhiyun *num_groups = pctl->functions[function].ngroups;
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun return 0;
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun
sunxi_pmx_set(struct pinctrl_dev * pctldev,unsigned pin,u8 config)709*4882a593Smuzhiyun static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
710*4882a593Smuzhiyun unsigned pin,
711*4882a593Smuzhiyun u8 config)
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
714*4882a593Smuzhiyun unsigned long flags;
715*4882a593Smuzhiyun u32 val, mask;
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun raw_spin_lock_irqsave(&pctl->lock, flags);
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun pin -= pctl->desc->pin_base;
720*4882a593Smuzhiyun val = readl(pctl->membase + sunxi_mux_reg(pin));
721*4882a593Smuzhiyun mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
722*4882a593Smuzhiyun writel((val & ~mask) | config << sunxi_mux_offset(pin),
723*4882a593Smuzhiyun pctl->membase + sunxi_mux_reg(pin));
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&pctl->lock, flags);
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun
sunxi_pmx_set_mux(struct pinctrl_dev * pctldev,unsigned function,unsigned group)728*4882a593Smuzhiyun static int sunxi_pmx_set_mux(struct pinctrl_dev *pctldev,
729*4882a593Smuzhiyun unsigned function,
730*4882a593Smuzhiyun unsigned group)
731*4882a593Smuzhiyun {
732*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
733*4882a593Smuzhiyun struct sunxi_pinctrl_group *g = pctl->groups + group;
734*4882a593Smuzhiyun struct sunxi_pinctrl_function *func = pctl->functions + function;
735*4882a593Smuzhiyun struct sunxi_desc_function *desc =
736*4882a593Smuzhiyun sunxi_pinctrl_desc_find_function_by_name(pctl,
737*4882a593Smuzhiyun g->name,
738*4882a593Smuzhiyun func->name);
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun if (!desc)
741*4882a593Smuzhiyun return -EINVAL;
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun sunxi_pmx_set(pctldev, g->pin, desc->muxval);
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun return 0;
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun static int
sunxi_pmx_gpio_set_direction(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned offset,bool input)749*4882a593Smuzhiyun sunxi_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
750*4882a593Smuzhiyun struct pinctrl_gpio_range *range,
751*4882a593Smuzhiyun unsigned offset,
752*4882a593Smuzhiyun bool input)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
755*4882a593Smuzhiyun struct sunxi_desc_function *desc;
756*4882a593Smuzhiyun const char *func;
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun if (input)
759*4882a593Smuzhiyun func = "gpio_in";
760*4882a593Smuzhiyun else
761*4882a593Smuzhiyun func = "gpio_out";
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, offset, func);
764*4882a593Smuzhiyun if (!desc)
765*4882a593Smuzhiyun return -EINVAL;
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun sunxi_pmx_set(pctldev, offset, desc->muxval);
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun return 0;
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun
sunxi_pmx_request(struct pinctrl_dev * pctldev,unsigned offset)772*4882a593Smuzhiyun static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
773*4882a593Smuzhiyun {
774*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
775*4882a593Smuzhiyun unsigned short bank = offset / PINS_PER_BANK;
776*4882a593Smuzhiyun unsigned short bank_offset = bank - pctl->desc->pin_base /
777*4882a593Smuzhiyun PINS_PER_BANK;
778*4882a593Smuzhiyun struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
779*4882a593Smuzhiyun struct regulator *reg = s_reg->regulator;
780*4882a593Smuzhiyun char supply[16];
781*4882a593Smuzhiyun int ret;
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun if (reg) {
784*4882a593Smuzhiyun refcount_inc(&s_reg->refcount);
785*4882a593Smuzhiyun return 0;
786*4882a593Smuzhiyun }
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
789*4882a593Smuzhiyun reg = regulator_get(pctl->dev, supply);
790*4882a593Smuzhiyun if (IS_ERR(reg)) {
791*4882a593Smuzhiyun dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
792*4882a593Smuzhiyun 'A' + bank);
793*4882a593Smuzhiyun return PTR_ERR(reg);
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun ret = regulator_enable(reg);
797*4882a593Smuzhiyun if (ret) {
798*4882a593Smuzhiyun dev_err(pctl->dev,
799*4882a593Smuzhiyun "Couldn't enable bank P%c regulator\n", 'A' + bank);
800*4882a593Smuzhiyun goto out;
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun sunxi_pinctrl_set_io_bias_cfg(pctl, offset, reg);
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun s_reg->regulator = reg;
806*4882a593Smuzhiyun refcount_set(&s_reg->refcount, 1);
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun return 0;
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun out:
811*4882a593Smuzhiyun regulator_put(s_reg->regulator);
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun return ret;
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun
sunxi_pmx_free(struct pinctrl_dev * pctldev,unsigned offset)816*4882a593Smuzhiyun static int sunxi_pmx_free(struct pinctrl_dev *pctldev, unsigned offset)
817*4882a593Smuzhiyun {
818*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
819*4882a593Smuzhiyun unsigned short bank = offset / PINS_PER_BANK;
820*4882a593Smuzhiyun unsigned short bank_offset = bank - pctl->desc->pin_base /
821*4882a593Smuzhiyun PINS_PER_BANK;
822*4882a593Smuzhiyun struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun if (!refcount_dec_and_test(&s_reg->refcount))
825*4882a593Smuzhiyun return 0;
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun regulator_disable(s_reg->regulator);
828*4882a593Smuzhiyun regulator_put(s_reg->regulator);
829*4882a593Smuzhiyun s_reg->regulator = NULL;
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun return 0;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun static const struct pinmux_ops sunxi_pmx_ops = {
835*4882a593Smuzhiyun .get_functions_count = sunxi_pmx_get_funcs_cnt,
836*4882a593Smuzhiyun .get_function_name = sunxi_pmx_get_func_name,
837*4882a593Smuzhiyun .get_function_groups = sunxi_pmx_get_func_groups,
838*4882a593Smuzhiyun .set_mux = sunxi_pmx_set_mux,
839*4882a593Smuzhiyun .gpio_set_direction = sunxi_pmx_gpio_set_direction,
840*4882a593Smuzhiyun .request = sunxi_pmx_request,
841*4882a593Smuzhiyun .free = sunxi_pmx_free,
842*4882a593Smuzhiyun .strict = true,
843*4882a593Smuzhiyun };
844*4882a593Smuzhiyun
sunxi_pinctrl_gpio_direction_input(struct gpio_chip * chip,unsigned offset)845*4882a593Smuzhiyun static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
846*4882a593Smuzhiyun unsigned offset)
847*4882a593Smuzhiyun {
848*4882a593Smuzhiyun return pinctrl_gpio_direction_input(chip->base + offset);
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun
sunxi_pinctrl_gpio_get(struct gpio_chip * chip,unsigned offset)851*4882a593Smuzhiyun static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
852*4882a593Smuzhiyun {
853*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = gpiochip_get_data(chip);
854*4882a593Smuzhiyun u32 reg = sunxi_data_reg(offset);
855*4882a593Smuzhiyun u8 index = sunxi_data_offset(offset);
856*4882a593Smuzhiyun bool set_mux = pctl->desc->irq_read_needs_mux &&
857*4882a593Smuzhiyun gpiochip_line_is_irq(chip, offset);
858*4882a593Smuzhiyun u32 pin = offset + chip->base;
859*4882a593Smuzhiyun u32 val;
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun if (set_mux)
862*4882a593Smuzhiyun sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_INPUT);
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun if (set_mux)
867*4882a593Smuzhiyun sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_IRQ);
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun return !!val;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
sunxi_pinctrl_gpio_set(struct gpio_chip * chip,unsigned offset,int value)872*4882a593Smuzhiyun static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
873*4882a593Smuzhiyun unsigned offset, int value)
874*4882a593Smuzhiyun {
875*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = gpiochip_get_data(chip);
876*4882a593Smuzhiyun u32 reg = sunxi_data_reg(offset);
877*4882a593Smuzhiyun u8 index = sunxi_data_offset(offset);
878*4882a593Smuzhiyun unsigned long flags;
879*4882a593Smuzhiyun u32 regval;
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun raw_spin_lock_irqsave(&pctl->lock, flags);
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun regval = readl(pctl->membase + reg);
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun if (value)
886*4882a593Smuzhiyun regval |= BIT(index);
887*4882a593Smuzhiyun else
888*4882a593Smuzhiyun regval &= ~(BIT(index));
889*4882a593Smuzhiyun
890*4882a593Smuzhiyun writel(regval, pctl->membase + reg);
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&pctl->lock, flags);
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun
sunxi_pinctrl_gpio_direction_output(struct gpio_chip * chip,unsigned offset,int value)895*4882a593Smuzhiyun static int sunxi_pinctrl_gpio_direction_output(struct gpio_chip *chip,
896*4882a593Smuzhiyun unsigned offset, int value)
897*4882a593Smuzhiyun {
898*4882a593Smuzhiyun sunxi_pinctrl_gpio_set(chip, offset, value);
899*4882a593Smuzhiyun return pinctrl_gpio_direction_output(chip->base + offset);
900*4882a593Smuzhiyun }
901*4882a593Smuzhiyun
sunxi_pinctrl_gpio_of_xlate(struct gpio_chip * gc,const struct of_phandle_args * gpiospec,u32 * flags)902*4882a593Smuzhiyun static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc,
903*4882a593Smuzhiyun const struct of_phandle_args *gpiospec,
904*4882a593Smuzhiyun u32 *flags)
905*4882a593Smuzhiyun {
906*4882a593Smuzhiyun int pin, base;
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun base = PINS_PER_BANK * gpiospec->args[0];
909*4882a593Smuzhiyun pin = base + gpiospec->args[1];
910*4882a593Smuzhiyun
911*4882a593Smuzhiyun if (pin > gc->ngpio)
912*4882a593Smuzhiyun return -EINVAL;
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun if (flags)
915*4882a593Smuzhiyun *flags = gpiospec->args[2];
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun return pin;
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun
sunxi_pinctrl_gpio_to_irq(struct gpio_chip * chip,unsigned offset)920*4882a593Smuzhiyun static int sunxi_pinctrl_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
921*4882a593Smuzhiyun {
922*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = gpiochip_get_data(chip);
923*4882a593Smuzhiyun struct sunxi_desc_function *desc;
924*4882a593Smuzhiyun unsigned pinnum = pctl->desc->pin_base + offset;
925*4882a593Smuzhiyun unsigned irqnum;
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun if (offset >= chip->ngpio)
928*4882a593Smuzhiyun return -ENXIO;
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pinnum, "irq");
931*4882a593Smuzhiyun if (!desc)
932*4882a593Smuzhiyun return -EINVAL;
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun irqnum = desc->irqbank * IRQ_PER_BANK + desc->irqnum;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun dev_dbg(chip->parent, "%s: request IRQ for GPIO %d, return %d\n",
937*4882a593Smuzhiyun chip->label, offset + chip->base, irqnum);
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun return irq_find_mapping(pctl->domain, irqnum);
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
sunxi_pinctrl_irq_request_resources(struct irq_data * d)942*4882a593Smuzhiyun static int sunxi_pinctrl_irq_request_resources(struct irq_data *d)
943*4882a593Smuzhiyun {
944*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
945*4882a593Smuzhiyun struct sunxi_desc_function *func;
946*4882a593Smuzhiyun int ret;
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun func = sunxi_pinctrl_desc_find_function_by_pin(pctl,
949*4882a593Smuzhiyun pctl->irq_array[d->hwirq], "irq");
950*4882a593Smuzhiyun if (!func)
951*4882a593Smuzhiyun return -EINVAL;
952*4882a593Smuzhiyun
953*4882a593Smuzhiyun ret = gpiochip_lock_as_irq(pctl->chip,
954*4882a593Smuzhiyun pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
955*4882a593Smuzhiyun if (ret) {
956*4882a593Smuzhiyun dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
957*4882a593Smuzhiyun irqd_to_hwirq(d));
958*4882a593Smuzhiyun return ret;
959*4882a593Smuzhiyun }
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun /* Change muxing to INT mode */
962*4882a593Smuzhiyun sunxi_pmx_set(pctl->pctl_dev, pctl->irq_array[d->hwirq], func->muxval);
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun return 0;
965*4882a593Smuzhiyun }
966*4882a593Smuzhiyun
sunxi_pinctrl_irq_release_resources(struct irq_data * d)967*4882a593Smuzhiyun static void sunxi_pinctrl_irq_release_resources(struct irq_data *d)
968*4882a593Smuzhiyun {
969*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun gpiochip_unlock_as_irq(pctl->chip,
972*4882a593Smuzhiyun pctl->irq_array[d->hwirq] - pctl->desc->pin_base);
973*4882a593Smuzhiyun }
974*4882a593Smuzhiyun
sunxi_pinctrl_irq_set_type(struct irq_data * d,unsigned int type)975*4882a593Smuzhiyun static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
976*4882a593Smuzhiyun {
977*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
978*4882a593Smuzhiyun u32 reg = sunxi_irq_cfg_reg(pctl->desc, d->hwirq);
979*4882a593Smuzhiyun u8 index = sunxi_irq_cfg_offset(d->hwirq);
980*4882a593Smuzhiyun unsigned long flags;
981*4882a593Smuzhiyun u32 regval;
982*4882a593Smuzhiyun u8 mode;
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun switch (type) {
985*4882a593Smuzhiyun case IRQ_TYPE_EDGE_RISING:
986*4882a593Smuzhiyun mode = IRQ_EDGE_RISING;
987*4882a593Smuzhiyun break;
988*4882a593Smuzhiyun case IRQ_TYPE_EDGE_FALLING:
989*4882a593Smuzhiyun mode = IRQ_EDGE_FALLING;
990*4882a593Smuzhiyun break;
991*4882a593Smuzhiyun case IRQ_TYPE_EDGE_BOTH:
992*4882a593Smuzhiyun mode = IRQ_EDGE_BOTH;
993*4882a593Smuzhiyun break;
994*4882a593Smuzhiyun case IRQ_TYPE_LEVEL_HIGH:
995*4882a593Smuzhiyun mode = IRQ_LEVEL_HIGH;
996*4882a593Smuzhiyun break;
997*4882a593Smuzhiyun case IRQ_TYPE_LEVEL_LOW:
998*4882a593Smuzhiyun mode = IRQ_LEVEL_LOW;
999*4882a593Smuzhiyun break;
1000*4882a593Smuzhiyun default:
1001*4882a593Smuzhiyun return -EINVAL;
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun raw_spin_lock_irqsave(&pctl->lock, flags);
1005*4882a593Smuzhiyun
1006*4882a593Smuzhiyun if (type & IRQ_TYPE_LEVEL_MASK)
1007*4882a593Smuzhiyun irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_level_irq_chip,
1008*4882a593Smuzhiyun handle_fasteoi_irq, NULL);
1009*4882a593Smuzhiyun else
1010*4882a593Smuzhiyun irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_edge_irq_chip,
1011*4882a593Smuzhiyun handle_edge_irq, NULL);
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun regval = readl(pctl->membase + reg);
1014*4882a593Smuzhiyun regval &= ~(IRQ_CFG_IRQ_MASK << index);
1015*4882a593Smuzhiyun writel(regval | (mode << index), pctl->membase + reg);
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&pctl->lock, flags);
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun return 0;
1020*4882a593Smuzhiyun }
1021*4882a593Smuzhiyun
sunxi_pinctrl_irq_ack(struct irq_data * d)1022*4882a593Smuzhiyun static void sunxi_pinctrl_irq_ack(struct irq_data *d)
1023*4882a593Smuzhiyun {
1024*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
1025*4882a593Smuzhiyun u32 status_reg = sunxi_irq_status_reg(pctl->desc, d->hwirq);
1026*4882a593Smuzhiyun u8 status_idx = sunxi_irq_status_offset(d->hwirq);
1027*4882a593Smuzhiyun
1028*4882a593Smuzhiyun /* Clear the IRQ */
1029*4882a593Smuzhiyun writel(1 << status_idx, pctl->membase + status_reg);
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun
sunxi_pinctrl_irq_mask(struct irq_data * d)1032*4882a593Smuzhiyun static void sunxi_pinctrl_irq_mask(struct irq_data *d)
1033*4882a593Smuzhiyun {
1034*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
1035*4882a593Smuzhiyun u32 reg = sunxi_irq_ctrl_reg(pctl->desc, d->hwirq);
1036*4882a593Smuzhiyun u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
1037*4882a593Smuzhiyun unsigned long flags;
1038*4882a593Smuzhiyun u32 val;
1039*4882a593Smuzhiyun
1040*4882a593Smuzhiyun raw_spin_lock_irqsave(&pctl->lock, flags);
1041*4882a593Smuzhiyun
1042*4882a593Smuzhiyun /* Mask the IRQ */
1043*4882a593Smuzhiyun val = readl(pctl->membase + reg);
1044*4882a593Smuzhiyun writel(val & ~(1 << idx), pctl->membase + reg);
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&pctl->lock, flags);
1047*4882a593Smuzhiyun }
1048*4882a593Smuzhiyun
sunxi_pinctrl_irq_unmask(struct irq_data * d)1049*4882a593Smuzhiyun static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
1050*4882a593Smuzhiyun {
1051*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
1052*4882a593Smuzhiyun u32 reg = sunxi_irq_ctrl_reg(pctl->desc, d->hwirq);
1053*4882a593Smuzhiyun u8 idx = sunxi_irq_ctrl_offset(d->hwirq);
1054*4882a593Smuzhiyun unsigned long flags;
1055*4882a593Smuzhiyun u32 val;
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun raw_spin_lock_irqsave(&pctl->lock, flags);
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun /* Unmask the IRQ */
1060*4882a593Smuzhiyun val = readl(pctl->membase + reg);
1061*4882a593Smuzhiyun writel(val | (1 << idx), pctl->membase + reg);
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&pctl->lock, flags);
1064*4882a593Smuzhiyun }
1065*4882a593Smuzhiyun
sunxi_pinctrl_irq_ack_unmask(struct irq_data * d)1066*4882a593Smuzhiyun static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d)
1067*4882a593Smuzhiyun {
1068*4882a593Smuzhiyun sunxi_pinctrl_irq_ack(d);
1069*4882a593Smuzhiyun sunxi_pinctrl_irq_unmask(d);
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun
sunxi_pinctrl_irq_set_wake(struct irq_data * d,unsigned int on)1072*4882a593Smuzhiyun static int sunxi_pinctrl_irq_set_wake(struct irq_data *d, unsigned int on)
1073*4882a593Smuzhiyun {
1074*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
1075*4882a593Smuzhiyun u8 bank = d->hwirq / IRQ_PER_BANK;
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun return irq_set_irq_wake(pctl->irq[bank], on);
1078*4882a593Smuzhiyun }
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun static struct irq_chip sunxi_pinctrl_edge_irq_chip = {
1081*4882a593Smuzhiyun .name = "sunxi_pio_edge",
1082*4882a593Smuzhiyun .irq_ack = sunxi_pinctrl_irq_ack,
1083*4882a593Smuzhiyun .irq_mask = sunxi_pinctrl_irq_mask,
1084*4882a593Smuzhiyun .irq_unmask = sunxi_pinctrl_irq_unmask,
1085*4882a593Smuzhiyun .irq_request_resources = sunxi_pinctrl_irq_request_resources,
1086*4882a593Smuzhiyun .irq_release_resources = sunxi_pinctrl_irq_release_resources,
1087*4882a593Smuzhiyun .irq_set_type = sunxi_pinctrl_irq_set_type,
1088*4882a593Smuzhiyun .irq_set_wake = sunxi_pinctrl_irq_set_wake,
1089*4882a593Smuzhiyun .flags = IRQCHIP_MASK_ON_SUSPEND,
1090*4882a593Smuzhiyun };
1091*4882a593Smuzhiyun
1092*4882a593Smuzhiyun static struct irq_chip sunxi_pinctrl_level_irq_chip = {
1093*4882a593Smuzhiyun .name = "sunxi_pio_level",
1094*4882a593Smuzhiyun .irq_eoi = sunxi_pinctrl_irq_ack,
1095*4882a593Smuzhiyun .irq_mask = sunxi_pinctrl_irq_mask,
1096*4882a593Smuzhiyun .irq_unmask = sunxi_pinctrl_irq_unmask,
1097*4882a593Smuzhiyun /* Define irq_enable / disable to avoid spurious irqs for drivers
1098*4882a593Smuzhiyun * using these to suppress irqs while they clear the irq source */
1099*4882a593Smuzhiyun .irq_enable = sunxi_pinctrl_irq_ack_unmask,
1100*4882a593Smuzhiyun .irq_disable = sunxi_pinctrl_irq_mask,
1101*4882a593Smuzhiyun .irq_request_resources = sunxi_pinctrl_irq_request_resources,
1102*4882a593Smuzhiyun .irq_release_resources = sunxi_pinctrl_irq_release_resources,
1103*4882a593Smuzhiyun .irq_set_type = sunxi_pinctrl_irq_set_type,
1104*4882a593Smuzhiyun .irq_set_wake = sunxi_pinctrl_irq_set_wake,
1105*4882a593Smuzhiyun .flags = IRQCHIP_EOI_THREADED |
1106*4882a593Smuzhiyun IRQCHIP_MASK_ON_SUSPEND |
1107*4882a593Smuzhiyun IRQCHIP_EOI_IF_HANDLED,
1108*4882a593Smuzhiyun };
1109*4882a593Smuzhiyun
sunxi_pinctrl_irq_of_xlate(struct irq_domain * d,struct device_node * node,const u32 * intspec,unsigned int intsize,unsigned long * out_hwirq,unsigned int * out_type)1110*4882a593Smuzhiyun static int sunxi_pinctrl_irq_of_xlate(struct irq_domain *d,
1111*4882a593Smuzhiyun struct device_node *node,
1112*4882a593Smuzhiyun const u32 *intspec,
1113*4882a593Smuzhiyun unsigned int intsize,
1114*4882a593Smuzhiyun unsigned long *out_hwirq,
1115*4882a593Smuzhiyun unsigned int *out_type)
1116*4882a593Smuzhiyun {
1117*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = d->host_data;
1118*4882a593Smuzhiyun struct sunxi_desc_function *desc;
1119*4882a593Smuzhiyun int pin, base;
1120*4882a593Smuzhiyun
1121*4882a593Smuzhiyun if (intsize < 3)
1122*4882a593Smuzhiyun return -EINVAL;
1123*4882a593Smuzhiyun
1124*4882a593Smuzhiyun base = PINS_PER_BANK * intspec[0];
1125*4882a593Smuzhiyun pin = pctl->desc->pin_base + base + intspec[1];
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun desc = sunxi_pinctrl_desc_find_function_by_pin(pctl, pin, "irq");
1128*4882a593Smuzhiyun if (!desc)
1129*4882a593Smuzhiyun return -EINVAL;
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun *out_hwirq = desc->irqbank * PINS_PER_BANK + desc->irqnum;
1132*4882a593Smuzhiyun *out_type = intspec[2];
1133*4882a593Smuzhiyun
1134*4882a593Smuzhiyun return 0;
1135*4882a593Smuzhiyun }
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun static const struct irq_domain_ops sunxi_pinctrl_irq_domain_ops = {
1138*4882a593Smuzhiyun .xlate = sunxi_pinctrl_irq_of_xlate,
1139*4882a593Smuzhiyun };
1140*4882a593Smuzhiyun
sunxi_pinctrl_irq_handler(struct irq_desc * desc)1141*4882a593Smuzhiyun static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
1142*4882a593Smuzhiyun {
1143*4882a593Smuzhiyun unsigned int irq = irq_desc_get_irq(desc);
1144*4882a593Smuzhiyun struct irq_chip *chip = irq_desc_get_chip(desc);
1145*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = irq_desc_get_handler_data(desc);
1146*4882a593Smuzhiyun unsigned long bank, reg, val;
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun for (bank = 0; bank < pctl->desc->irq_banks; bank++)
1149*4882a593Smuzhiyun if (irq == pctl->irq[bank])
1150*4882a593Smuzhiyun break;
1151*4882a593Smuzhiyun
1152*4882a593Smuzhiyun if (bank == pctl->desc->irq_banks)
1153*4882a593Smuzhiyun return;
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun chained_irq_enter(chip, desc);
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun reg = sunxi_irq_status_reg_from_bank(pctl->desc, bank);
1158*4882a593Smuzhiyun val = readl(pctl->membase + reg);
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun if (val) {
1161*4882a593Smuzhiyun int irqoffset;
1162*4882a593Smuzhiyun
1163*4882a593Smuzhiyun for_each_set_bit(irqoffset, &val, IRQ_PER_BANK) {
1164*4882a593Smuzhiyun int pin_irq = irq_find_mapping(pctl->domain,
1165*4882a593Smuzhiyun bank * IRQ_PER_BANK + irqoffset);
1166*4882a593Smuzhiyun generic_handle_irq(pin_irq);
1167*4882a593Smuzhiyun }
1168*4882a593Smuzhiyun }
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun chained_irq_exit(chip, desc);
1171*4882a593Smuzhiyun }
1172*4882a593Smuzhiyun
sunxi_pinctrl_add_function(struct sunxi_pinctrl * pctl,const char * name)1173*4882a593Smuzhiyun static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl,
1174*4882a593Smuzhiyun const char *name)
1175*4882a593Smuzhiyun {
1176*4882a593Smuzhiyun struct sunxi_pinctrl_function *func = pctl->functions;
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun while (func->name) {
1179*4882a593Smuzhiyun /* function already there */
1180*4882a593Smuzhiyun if (strcmp(func->name, name) == 0) {
1181*4882a593Smuzhiyun func->ngroups++;
1182*4882a593Smuzhiyun return -EEXIST;
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun func++;
1185*4882a593Smuzhiyun }
1186*4882a593Smuzhiyun
1187*4882a593Smuzhiyun func->name = name;
1188*4882a593Smuzhiyun func->ngroups = 1;
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun pctl->nfunctions++;
1191*4882a593Smuzhiyun
1192*4882a593Smuzhiyun return 0;
1193*4882a593Smuzhiyun }
1194*4882a593Smuzhiyun
sunxi_pinctrl_build_state(struct platform_device * pdev)1195*4882a593Smuzhiyun static int sunxi_pinctrl_build_state(struct platform_device *pdev)
1196*4882a593Smuzhiyun {
1197*4882a593Smuzhiyun struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
1198*4882a593Smuzhiyun void *ptr;
1199*4882a593Smuzhiyun int i;
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun /*
1202*4882a593Smuzhiyun * Allocate groups
1203*4882a593Smuzhiyun *
1204*4882a593Smuzhiyun * We assume that the number of groups is the number of pins
1205*4882a593Smuzhiyun * given in the data array.
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun * This will not always be true, since some pins might not be
1208*4882a593Smuzhiyun * available in the current variant, but fortunately for us,
1209*4882a593Smuzhiyun * this means that the number of pins is the maximum group
1210*4882a593Smuzhiyun * number we will ever see.
1211*4882a593Smuzhiyun */
1212*4882a593Smuzhiyun pctl->groups = devm_kcalloc(&pdev->dev,
1213*4882a593Smuzhiyun pctl->desc->npins, sizeof(*pctl->groups),
1214*4882a593Smuzhiyun GFP_KERNEL);
1215*4882a593Smuzhiyun if (!pctl->groups)
1216*4882a593Smuzhiyun return -ENOMEM;
1217*4882a593Smuzhiyun
1218*4882a593Smuzhiyun for (i = 0; i < pctl->desc->npins; i++) {
1219*4882a593Smuzhiyun const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
1220*4882a593Smuzhiyun struct sunxi_pinctrl_group *group = pctl->groups + pctl->ngroups;
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun if (pin->variant && !(pctl->variant & pin->variant))
1223*4882a593Smuzhiyun continue;
1224*4882a593Smuzhiyun
1225*4882a593Smuzhiyun group->name = pin->pin.name;
1226*4882a593Smuzhiyun group->pin = pin->pin.number;
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyun /* And now we count the actual number of pins / groups */
1229*4882a593Smuzhiyun pctl->ngroups++;
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun /*
1233*4882a593Smuzhiyun * We suppose that we won't have any more functions than pins,
1234*4882a593Smuzhiyun * we'll reallocate that later anyway
1235*4882a593Smuzhiyun */
1236*4882a593Smuzhiyun pctl->functions = kcalloc(pctl->ngroups,
1237*4882a593Smuzhiyun sizeof(*pctl->functions),
1238*4882a593Smuzhiyun GFP_KERNEL);
1239*4882a593Smuzhiyun if (!pctl->functions)
1240*4882a593Smuzhiyun return -ENOMEM;
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun /* Count functions and their associated groups */
1243*4882a593Smuzhiyun for (i = 0; i < pctl->desc->npins; i++) {
1244*4882a593Smuzhiyun const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
1245*4882a593Smuzhiyun struct sunxi_desc_function *func;
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun if (pin->variant && !(pctl->variant & pin->variant))
1248*4882a593Smuzhiyun continue;
1249*4882a593Smuzhiyun
1250*4882a593Smuzhiyun for (func = pin->functions; func->name; func++) {
1251*4882a593Smuzhiyun if (func->variant && !(pctl->variant & func->variant))
1252*4882a593Smuzhiyun continue;
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun /* Create interrupt mapping while we're at it */
1255*4882a593Smuzhiyun if (!strcmp(func->name, "irq")) {
1256*4882a593Smuzhiyun int irqnum = func->irqnum + func->irqbank * IRQ_PER_BANK;
1257*4882a593Smuzhiyun pctl->irq_array[irqnum] = pin->pin.number;
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun sunxi_pinctrl_add_function(pctl, func->name);
1261*4882a593Smuzhiyun }
1262*4882a593Smuzhiyun }
1263*4882a593Smuzhiyun
1264*4882a593Smuzhiyun /* And now allocated and fill the array for real */
1265*4882a593Smuzhiyun ptr = krealloc(pctl->functions,
1266*4882a593Smuzhiyun pctl->nfunctions * sizeof(*pctl->functions),
1267*4882a593Smuzhiyun GFP_KERNEL);
1268*4882a593Smuzhiyun if (!ptr) {
1269*4882a593Smuzhiyun kfree(pctl->functions);
1270*4882a593Smuzhiyun pctl->functions = NULL;
1271*4882a593Smuzhiyun return -ENOMEM;
1272*4882a593Smuzhiyun }
1273*4882a593Smuzhiyun pctl->functions = ptr;
1274*4882a593Smuzhiyun
1275*4882a593Smuzhiyun for (i = 0; i < pctl->desc->npins; i++) {
1276*4882a593Smuzhiyun const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
1277*4882a593Smuzhiyun struct sunxi_desc_function *func;
1278*4882a593Smuzhiyun
1279*4882a593Smuzhiyun if (pin->variant && !(pctl->variant & pin->variant))
1280*4882a593Smuzhiyun continue;
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun for (func = pin->functions; func->name; func++) {
1283*4882a593Smuzhiyun struct sunxi_pinctrl_function *func_item;
1284*4882a593Smuzhiyun const char **func_grp;
1285*4882a593Smuzhiyun
1286*4882a593Smuzhiyun if (func->variant && !(pctl->variant & func->variant))
1287*4882a593Smuzhiyun continue;
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun func_item = sunxi_pinctrl_find_function_by_name(pctl,
1290*4882a593Smuzhiyun func->name);
1291*4882a593Smuzhiyun if (!func_item) {
1292*4882a593Smuzhiyun kfree(pctl->functions);
1293*4882a593Smuzhiyun return -EINVAL;
1294*4882a593Smuzhiyun }
1295*4882a593Smuzhiyun
1296*4882a593Smuzhiyun if (!func_item->groups) {
1297*4882a593Smuzhiyun func_item->groups =
1298*4882a593Smuzhiyun devm_kcalloc(&pdev->dev,
1299*4882a593Smuzhiyun func_item->ngroups,
1300*4882a593Smuzhiyun sizeof(*func_item->groups),
1301*4882a593Smuzhiyun GFP_KERNEL);
1302*4882a593Smuzhiyun if (!func_item->groups) {
1303*4882a593Smuzhiyun kfree(pctl->functions);
1304*4882a593Smuzhiyun return -ENOMEM;
1305*4882a593Smuzhiyun }
1306*4882a593Smuzhiyun }
1307*4882a593Smuzhiyun
1308*4882a593Smuzhiyun func_grp = func_item->groups;
1309*4882a593Smuzhiyun while (*func_grp)
1310*4882a593Smuzhiyun func_grp++;
1311*4882a593Smuzhiyun
1312*4882a593Smuzhiyun *func_grp = pin->pin.name;
1313*4882a593Smuzhiyun }
1314*4882a593Smuzhiyun }
1315*4882a593Smuzhiyun
1316*4882a593Smuzhiyun return 0;
1317*4882a593Smuzhiyun }
1318*4882a593Smuzhiyun
sunxi_pinctrl_get_debounce_div(struct clk * clk,int freq,int * diff)1319*4882a593Smuzhiyun static int sunxi_pinctrl_get_debounce_div(struct clk *clk, int freq, int *diff)
1320*4882a593Smuzhiyun {
1321*4882a593Smuzhiyun unsigned long clock = clk_get_rate(clk);
1322*4882a593Smuzhiyun unsigned int best_diff, best_div;
1323*4882a593Smuzhiyun int i;
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun best_diff = abs(freq - clock);
1326*4882a593Smuzhiyun best_div = 0;
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun for (i = 1; i < 8; i++) {
1329*4882a593Smuzhiyun int cur_diff = abs(freq - (clock >> i));
1330*4882a593Smuzhiyun
1331*4882a593Smuzhiyun if (cur_diff < best_diff) {
1332*4882a593Smuzhiyun best_diff = cur_diff;
1333*4882a593Smuzhiyun best_div = i;
1334*4882a593Smuzhiyun }
1335*4882a593Smuzhiyun }
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun *diff = best_diff;
1338*4882a593Smuzhiyun return best_div;
1339*4882a593Smuzhiyun }
1340*4882a593Smuzhiyun
sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl * pctl,struct device_node * node)1341*4882a593Smuzhiyun static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
1342*4882a593Smuzhiyun struct device_node *node)
1343*4882a593Smuzhiyun {
1344*4882a593Smuzhiyun unsigned int hosc_diff, losc_diff;
1345*4882a593Smuzhiyun unsigned int hosc_div, losc_div;
1346*4882a593Smuzhiyun struct clk *hosc, *losc;
1347*4882a593Smuzhiyun u8 div, src;
1348*4882a593Smuzhiyun int i, ret;
1349*4882a593Smuzhiyun
1350*4882a593Smuzhiyun /* Deal with old DTs that didn't have the oscillators */
1351*4882a593Smuzhiyun if (of_clk_get_parent_count(node) != 3)
1352*4882a593Smuzhiyun return 0;
1353*4882a593Smuzhiyun
1354*4882a593Smuzhiyun /* If we don't have any setup, bail out */
1355*4882a593Smuzhiyun if (!of_find_property(node, "input-debounce", NULL))
1356*4882a593Smuzhiyun return 0;
1357*4882a593Smuzhiyun
1358*4882a593Smuzhiyun losc = devm_clk_get(pctl->dev, "losc");
1359*4882a593Smuzhiyun if (IS_ERR(losc))
1360*4882a593Smuzhiyun return PTR_ERR(losc);
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun hosc = devm_clk_get(pctl->dev, "hosc");
1363*4882a593Smuzhiyun if (IS_ERR(hosc))
1364*4882a593Smuzhiyun return PTR_ERR(hosc);
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun for (i = 0; i < pctl->desc->irq_banks; i++) {
1367*4882a593Smuzhiyun unsigned long debounce_freq;
1368*4882a593Smuzhiyun u32 debounce;
1369*4882a593Smuzhiyun
1370*4882a593Smuzhiyun ret = of_property_read_u32_index(node, "input-debounce",
1371*4882a593Smuzhiyun i, &debounce);
1372*4882a593Smuzhiyun if (ret)
1373*4882a593Smuzhiyun return ret;
1374*4882a593Smuzhiyun
1375*4882a593Smuzhiyun if (!debounce)
1376*4882a593Smuzhiyun continue;
1377*4882a593Smuzhiyun
1378*4882a593Smuzhiyun debounce_freq = DIV_ROUND_CLOSEST(USEC_PER_SEC, debounce);
1379*4882a593Smuzhiyun losc_div = sunxi_pinctrl_get_debounce_div(losc,
1380*4882a593Smuzhiyun debounce_freq,
1381*4882a593Smuzhiyun &losc_diff);
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun hosc_div = sunxi_pinctrl_get_debounce_div(hosc,
1384*4882a593Smuzhiyun debounce_freq,
1385*4882a593Smuzhiyun &hosc_diff);
1386*4882a593Smuzhiyun
1387*4882a593Smuzhiyun if (hosc_diff < losc_diff) {
1388*4882a593Smuzhiyun div = hosc_div;
1389*4882a593Smuzhiyun src = 1;
1390*4882a593Smuzhiyun } else {
1391*4882a593Smuzhiyun div = losc_div;
1392*4882a593Smuzhiyun src = 0;
1393*4882a593Smuzhiyun }
1394*4882a593Smuzhiyun
1395*4882a593Smuzhiyun writel(src | div << 4,
1396*4882a593Smuzhiyun pctl->membase +
1397*4882a593Smuzhiyun sunxi_irq_debounce_reg_from_bank(pctl->desc, i));
1398*4882a593Smuzhiyun }
1399*4882a593Smuzhiyun
1400*4882a593Smuzhiyun return 0;
1401*4882a593Smuzhiyun }
1402*4882a593Smuzhiyun
sunxi_pinctrl_init_with_variant(struct platform_device * pdev,const struct sunxi_pinctrl_desc * desc,unsigned long variant)1403*4882a593Smuzhiyun int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
1404*4882a593Smuzhiyun const struct sunxi_pinctrl_desc *desc,
1405*4882a593Smuzhiyun unsigned long variant)
1406*4882a593Smuzhiyun {
1407*4882a593Smuzhiyun struct device_node *node = pdev->dev.of_node;
1408*4882a593Smuzhiyun struct pinctrl_desc *pctrl_desc;
1409*4882a593Smuzhiyun struct pinctrl_pin_desc *pins;
1410*4882a593Smuzhiyun struct sunxi_pinctrl *pctl;
1411*4882a593Smuzhiyun struct pinmux_ops *pmxops;
1412*4882a593Smuzhiyun int i, ret, last_pin, pin_idx;
1413*4882a593Smuzhiyun struct clk *clk;
1414*4882a593Smuzhiyun
1415*4882a593Smuzhiyun pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
1416*4882a593Smuzhiyun if (!pctl)
1417*4882a593Smuzhiyun return -ENOMEM;
1418*4882a593Smuzhiyun platform_set_drvdata(pdev, pctl);
1419*4882a593Smuzhiyun
1420*4882a593Smuzhiyun raw_spin_lock_init(&pctl->lock);
1421*4882a593Smuzhiyun
1422*4882a593Smuzhiyun pctl->membase = devm_platform_ioremap_resource(pdev, 0);
1423*4882a593Smuzhiyun if (IS_ERR(pctl->membase))
1424*4882a593Smuzhiyun return PTR_ERR(pctl->membase);
1425*4882a593Smuzhiyun
1426*4882a593Smuzhiyun pctl->dev = &pdev->dev;
1427*4882a593Smuzhiyun pctl->desc = desc;
1428*4882a593Smuzhiyun pctl->variant = variant;
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun pctl->irq_array = devm_kcalloc(&pdev->dev,
1431*4882a593Smuzhiyun IRQ_PER_BANK * pctl->desc->irq_banks,
1432*4882a593Smuzhiyun sizeof(*pctl->irq_array),
1433*4882a593Smuzhiyun GFP_KERNEL);
1434*4882a593Smuzhiyun if (!pctl->irq_array)
1435*4882a593Smuzhiyun return -ENOMEM;
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun ret = sunxi_pinctrl_build_state(pdev);
1438*4882a593Smuzhiyun if (ret) {
1439*4882a593Smuzhiyun dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
1440*4882a593Smuzhiyun return ret;
1441*4882a593Smuzhiyun }
1442*4882a593Smuzhiyun
1443*4882a593Smuzhiyun pins = devm_kcalloc(&pdev->dev,
1444*4882a593Smuzhiyun pctl->desc->npins, sizeof(*pins),
1445*4882a593Smuzhiyun GFP_KERNEL);
1446*4882a593Smuzhiyun if (!pins)
1447*4882a593Smuzhiyun return -ENOMEM;
1448*4882a593Smuzhiyun
1449*4882a593Smuzhiyun for (i = 0, pin_idx = 0; i < pctl->desc->npins; i++) {
1450*4882a593Smuzhiyun const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
1451*4882a593Smuzhiyun
1452*4882a593Smuzhiyun if (pin->variant && !(pctl->variant & pin->variant))
1453*4882a593Smuzhiyun continue;
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun pins[pin_idx++] = pin->pin;
1456*4882a593Smuzhiyun }
1457*4882a593Smuzhiyun
1458*4882a593Smuzhiyun pctrl_desc = devm_kzalloc(&pdev->dev,
1459*4882a593Smuzhiyun sizeof(*pctrl_desc),
1460*4882a593Smuzhiyun GFP_KERNEL);
1461*4882a593Smuzhiyun if (!pctrl_desc)
1462*4882a593Smuzhiyun return -ENOMEM;
1463*4882a593Smuzhiyun
1464*4882a593Smuzhiyun pctrl_desc->name = dev_name(&pdev->dev);
1465*4882a593Smuzhiyun pctrl_desc->owner = THIS_MODULE;
1466*4882a593Smuzhiyun pctrl_desc->pins = pins;
1467*4882a593Smuzhiyun pctrl_desc->npins = pctl->ngroups;
1468*4882a593Smuzhiyun pctrl_desc->confops = &sunxi_pconf_ops;
1469*4882a593Smuzhiyun pctrl_desc->pctlops = &sunxi_pctrl_ops;
1470*4882a593Smuzhiyun
1471*4882a593Smuzhiyun pmxops = devm_kmemdup(&pdev->dev, &sunxi_pmx_ops, sizeof(sunxi_pmx_ops),
1472*4882a593Smuzhiyun GFP_KERNEL);
1473*4882a593Smuzhiyun if (!pmxops)
1474*4882a593Smuzhiyun return -ENOMEM;
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun if (desc->disable_strict_mode)
1477*4882a593Smuzhiyun pmxops->strict = false;
1478*4882a593Smuzhiyun
1479*4882a593Smuzhiyun pctrl_desc->pmxops = pmxops;
1480*4882a593Smuzhiyun
1481*4882a593Smuzhiyun pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, pctrl_desc, pctl);
1482*4882a593Smuzhiyun if (IS_ERR(pctl->pctl_dev)) {
1483*4882a593Smuzhiyun dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
1484*4882a593Smuzhiyun return PTR_ERR(pctl->pctl_dev);
1485*4882a593Smuzhiyun }
1486*4882a593Smuzhiyun
1487*4882a593Smuzhiyun pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
1488*4882a593Smuzhiyun if (!pctl->chip)
1489*4882a593Smuzhiyun return -ENOMEM;
1490*4882a593Smuzhiyun
1491*4882a593Smuzhiyun last_pin = pctl->desc->pins[pctl->desc->npins - 1].pin.number;
1492*4882a593Smuzhiyun pctl->chip->owner = THIS_MODULE;
1493*4882a593Smuzhiyun pctl->chip->request = gpiochip_generic_request;
1494*4882a593Smuzhiyun pctl->chip->free = gpiochip_generic_free;
1495*4882a593Smuzhiyun pctl->chip->set_config = gpiochip_generic_config;
1496*4882a593Smuzhiyun pctl->chip->direction_input = sunxi_pinctrl_gpio_direction_input;
1497*4882a593Smuzhiyun pctl->chip->direction_output = sunxi_pinctrl_gpio_direction_output;
1498*4882a593Smuzhiyun pctl->chip->get = sunxi_pinctrl_gpio_get;
1499*4882a593Smuzhiyun pctl->chip->set = sunxi_pinctrl_gpio_set;
1500*4882a593Smuzhiyun pctl->chip->of_xlate = sunxi_pinctrl_gpio_of_xlate;
1501*4882a593Smuzhiyun pctl->chip->to_irq = sunxi_pinctrl_gpio_to_irq;
1502*4882a593Smuzhiyun pctl->chip->of_gpio_n_cells = 3;
1503*4882a593Smuzhiyun pctl->chip->can_sleep = false;
1504*4882a593Smuzhiyun pctl->chip->ngpio = round_up(last_pin, PINS_PER_BANK) -
1505*4882a593Smuzhiyun pctl->desc->pin_base;
1506*4882a593Smuzhiyun pctl->chip->label = dev_name(&pdev->dev);
1507*4882a593Smuzhiyun pctl->chip->parent = &pdev->dev;
1508*4882a593Smuzhiyun pctl->chip->base = pctl->desc->pin_base;
1509*4882a593Smuzhiyun
1510*4882a593Smuzhiyun ret = gpiochip_add_data(pctl->chip, pctl);
1511*4882a593Smuzhiyun if (ret)
1512*4882a593Smuzhiyun return ret;
1513*4882a593Smuzhiyun
1514*4882a593Smuzhiyun for (i = 0; i < pctl->desc->npins; i++) {
1515*4882a593Smuzhiyun const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
1516*4882a593Smuzhiyun
1517*4882a593Smuzhiyun ret = gpiochip_add_pin_range(pctl->chip, dev_name(&pdev->dev),
1518*4882a593Smuzhiyun pin->pin.number - pctl->desc->pin_base,
1519*4882a593Smuzhiyun pin->pin.number, 1);
1520*4882a593Smuzhiyun if (ret)
1521*4882a593Smuzhiyun goto gpiochip_error;
1522*4882a593Smuzhiyun }
1523*4882a593Smuzhiyun
1524*4882a593Smuzhiyun ret = of_clk_get_parent_count(node);
1525*4882a593Smuzhiyun clk = devm_clk_get(&pdev->dev, ret == 1 ? NULL : "apb");
1526*4882a593Smuzhiyun if (IS_ERR(clk)) {
1527*4882a593Smuzhiyun ret = PTR_ERR(clk);
1528*4882a593Smuzhiyun goto gpiochip_error;
1529*4882a593Smuzhiyun }
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun ret = clk_prepare_enable(clk);
1532*4882a593Smuzhiyun if (ret)
1533*4882a593Smuzhiyun goto gpiochip_error;
1534*4882a593Smuzhiyun
1535*4882a593Smuzhiyun pctl->irq = devm_kcalloc(&pdev->dev,
1536*4882a593Smuzhiyun pctl->desc->irq_banks,
1537*4882a593Smuzhiyun sizeof(*pctl->irq),
1538*4882a593Smuzhiyun GFP_KERNEL);
1539*4882a593Smuzhiyun if (!pctl->irq) {
1540*4882a593Smuzhiyun ret = -ENOMEM;
1541*4882a593Smuzhiyun goto clk_error;
1542*4882a593Smuzhiyun }
1543*4882a593Smuzhiyun
1544*4882a593Smuzhiyun for (i = 0; i < pctl->desc->irq_banks; i++) {
1545*4882a593Smuzhiyun pctl->irq[i] = platform_get_irq(pdev, i);
1546*4882a593Smuzhiyun if (pctl->irq[i] < 0) {
1547*4882a593Smuzhiyun ret = pctl->irq[i];
1548*4882a593Smuzhiyun goto clk_error;
1549*4882a593Smuzhiyun }
1550*4882a593Smuzhiyun }
1551*4882a593Smuzhiyun
1552*4882a593Smuzhiyun pctl->domain = irq_domain_add_linear(node,
1553*4882a593Smuzhiyun pctl->desc->irq_banks * IRQ_PER_BANK,
1554*4882a593Smuzhiyun &sunxi_pinctrl_irq_domain_ops,
1555*4882a593Smuzhiyun pctl);
1556*4882a593Smuzhiyun if (!pctl->domain) {
1557*4882a593Smuzhiyun dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
1558*4882a593Smuzhiyun ret = -ENOMEM;
1559*4882a593Smuzhiyun goto clk_error;
1560*4882a593Smuzhiyun }
1561*4882a593Smuzhiyun
1562*4882a593Smuzhiyun for (i = 0; i < (pctl->desc->irq_banks * IRQ_PER_BANK); i++) {
1563*4882a593Smuzhiyun int irqno = irq_create_mapping(pctl->domain, i);
1564*4882a593Smuzhiyun
1565*4882a593Smuzhiyun irq_set_lockdep_class(irqno, &sunxi_pinctrl_irq_lock_class,
1566*4882a593Smuzhiyun &sunxi_pinctrl_irq_request_class);
1567*4882a593Smuzhiyun irq_set_chip_and_handler(irqno, &sunxi_pinctrl_edge_irq_chip,
1568*4882a593Smuzhiyun handle_edge_irq);
1569*4882a593Smuzhiyun irq_set_chip_data(irqno, pctl);
1570*4882a593Smuzhiyun }
1571*4882a593Smuzhiyun
1572*4882a593Smuzhiyun for (i = 0; i < pctl->desc->irq_banks; i++) {
1573*4882a593Smuzhiyun /* Mask and clear all IRQs before registering a handler */
1574*4882a593Smuzhiyun writel(0, pctl->membase +
1575*4882a593Smuzhiyun sunxi_irq_ctrl_reg_from_bank(pctl->desc, i));
1576*4882a593Smuzhiyun writel(0xffffffff,
1577*4882a593Smuzhiyun pctl->membase +
1578*4882a593Smuzhiyun sunxi_irq_status_reg_from_bank(pctl->desc, i));
1579*4882a593Smuzhiyun
1580*4882a593Smuzhiyun irq_set_chained_handler_and_data(pctl->irq[i],
1581*4882a593Smuzhiyun sunxi_pinctrl_irq_handler,
1582*4882a593Smuzhiyun pctl);
1583*4882a593Smuzhiyun }
1584*4882a593Smuzhiyun
1585*4882a593Smuzhiyun sunxi_pinctrl_setup_debounce(pctl, node);
1586*4882a593Smuzhiyun
1587*4882a593Smuzhiyun dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
1588*4882a593Smuzhiyun
1589*4882a593Smuzhiyun return 0;
1590*4882a593Smuzhiyun
1591*4882a593Smuzhiyun clk_error:
1592*4882a593Smuzhiyun clk_disable_unprepare(clk);
1593*4882a593Smuzhiyun gpiochip_error:
1594*4882a593Smuzhiyun gpiochip_remove(pctl->chip);
1595*4882a593Smuzhiyun return ret;
1596*4882a593Smuzhiyun }
1597