ARM: sunxi: Add pinctrl driver for Allwinner SoCs
[linux-2.6-block.git] / drivers / pinctrl / pinctrl-sunxi.c
1 /*
2  * Allwinner A1X SoCs pinctrl driver.
3  *
4  * Copyright (C) 2012 Maxime Ripard
5  *
6  * Maxime Ripard <maxime.ripard@free-electrons.com>
7  *
8  * This file is licensed under the terms of the GNU General Public
9  * License version 2.  This program is licensed "as is" without any
10  * warranty of any kind, whether express or implied.
11  */
12
13 #include <linux/io.h>
14 #include <linux/module.h>
15 #include <linux/of.h>
16 #include <linux/of_address.h>
17 #include <linux/of_device.h>
18 #include <linux/pinctrl/consumer.h>
19 #include <linux/pinctrl/machine.h>
20 #include <linux/pinctrl/pinctrl.h>
21 #include <linux/pinctrl/pinconf-generic.h>
22 #include <linux/pinctrl/pinmux.h>
23 #include <linux/platform_device.h>
24 #include <linux/slab.h>
25
26 #include "core.h"
27 #include "pinctrl-sunxi.h"
28
29 static struct sunxi_pinctrl_group *
30 sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group)
31 {
32         int i;
33
34         for (i = 0; i < pctl->ngroups; i++) {
35                 struct sunxi_pinctrl_group *grp = pctl->groups + i;
36
37                 if (!strcmp(grp->name, group))
38                         return grp;
39         }
40
41         return NULL;
42 }
43
44 static struct sunxi_pinctrl_function *
45 sunxi_pinctrl_find_function_by_name(struct sunxi_pinctrl *pctl,
46                                     const char *name)
47 {
48         struct sunxi_pinctrl_function *func = pctl->functions;
49         int i;
50
51         for (i = 0; i < pctl->nfunctions; i++) {
52                 if (!func[i].name)
53                         break;
54
55                 if (!strcmp(func[i].name, name))
56                         return func + i;
57         }
58
59         return NULL;
60 }
61
62 static struct sunxi_desc_function *
63 sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl,
64                                          const char *pin_name,
65                                          const char *func_name)
66 {
67         int i;
68
69         for (i = 0; i < pctl->desc->npins; i++) {
70                 const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
71
72                 if (!strcmp(pin->pin.name, pin_name)) {
73                         struct sunxi_desc_function *func = pin->functions;
74
75                         while (func->name) {
76                                 if (!strcmp(func->name, func_name))
77                                         return func;
78
79                                 func++;
80                         }
81                 }
82         }
83
84         return NULL;
85 }
86
87 static int sunxi_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
88 {
89         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
90
91         return pctl->ngroups;
92 }
93
94 static const char *sunxi_pctrl_get_group_name(struct pinctrl_dev *pctldev,
95                                               unsigned group)
96 {
97         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
98
99         return pctl->groups[group].name;
100 }
101
102 static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
103                                       unsigned group,
104                                       const unsigned **pins,
105                                       unsigned *num_pins)
106 {
107         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
108
109         *pins = (unsigned *)&pctl->groups[group].pin;
110         *num_pins = 1;
111
112         return 0;
113 }
114
115 static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
116                                       struct device_node *node,
117                                       struct pinctrl_map **map,
118                                       unsigned *num_maps)
119 {
120         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
121         unsigned long *pinconfig;
122         struct property *prop;
123         const char *function;
124         const char *group;
125         int ret, nmaps, i = 0;
126         u32 val;
127
128         *map = NULL;
129         *num_maps = 0;
130
131         ret = of_property_read_string(node, "allwinner,function", &function);
132         if (ret) {
133                 dev_err(pctl->dev,
134                         "missing allwinner,function property in node %s\n",
135                         node->name);
136                 return -EINVAL;
137         }
138
139         nmaps = of_property_count_strings(node, "allwinner,pins") * 2;
140         if (nmaps < 0) {
141                 dev_err(pctl->dev,
142                         "missing allwinner,pins property in node %s\n",
143                         node->name);
144                 return -EINVAL;
145         }
146
147         *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
148         if (!map)
149                 return -ENOMEM;
150
151         of_property_for_each_string(node, "allwinner,pins", prop, group) {
152                 struct sunxi_pinctrl_group *grp =
153                         sunxi_pinctrl_find_group_by_name(pctl, group);
154                 int j = 0, configlen = 0;
155
156                 if (!grp) {
157                         dev_err(pctl->dev, "unknown pin %s", group);
158                         continue;
159                 }
160
161                 if (!sunxi_pinctrl_desc_find_function_by_name(pctl,
162                                                               grp->name,
163                                                               function)) {
164                         dev_err(pctl->dev, "unsupported function %s on pin %s",
165                                 function, group);
166                         continue;
167                 }
168
169                 (*map)[i].type = PIN_MAP_TYPE_MUX_GROUP;
170                 (*map)[i].data.mux.group = group;
171                 (*map)[i].data.mux.function = function;
172
173                 i++;
174
175                 (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
176                 (*map)[i].data.configs.group_or_pin = group;
177
178                 if (of_find_property(node, "allwinner,drive", NULL))
179                         configlen++;
180                 if (of_find_property(node, "allwinner,pull", NULL))
181                         configlen++;
182
183                 pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL);
184
185                 if (!of_property_read_u32(node, "allwinner,drive", &val)) {
186                         u16 strength = (val + 1) * 10;
187                         pinconfig[j++] =
188                                 pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH,
189                                                          strength);
190                 }
191
192                 if (!of_property_read_u32(node, "allwinner,pull", &val)) {
193                         enum pin_config_param pull = PIN_CONFIG_END;
194                         if (val == 1)
195                                 pull = PIN_CONFIG_BIAS_PULL_UP;
196                         else if (val == 2)
197                                 pull = PIN_CONFIG_BIAS_PULL_DOWN;
198                         pinconfig[j++] = pinconf_to_config_packed(pull, 0);
199                 }
200
201                 (*map)[i].data.configs.configs = pinconfig;
202                 (*map)[i].data.configs.num_configs = configlen;
203
204                 i++;
205         }
206
207         *num_maps = nmaps;
208
209         return 0;
210 }
211
212 static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
213                                     struct pinctrl_map *map,
214                                     unsigned num_maps)
215 {
216         int i;
217
218         for (i = 0; i < num_maps; i++) {
219                 if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
220                         kfree(map[i].data.configs.configs);
221         }
222
223         kfree(map);
224 }
225
226 static struct pinctrl_ops sunxi_pctrl_ops = {
227         .dt_node_to_map         = sunxi_pctrl_dt_node_to_map,
228         .dt_free_map            = sunxi_pctrl_dt_free_map,
229         .get_groups_count       = sunxi_pctrl_get_groups_count,
230         .get_group_name         = sunxi_pctrl_get_group_name,
231         .get_group_pins         = sunxi_pctrl_get_group_pins,
232 };
233
234 static int sunxi_pconf_group_get(struct pinctrl_dev *pctldev,
235                                  unsigned group,
236                                  unsigned long *config)
237 {
238         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
239
240         *config = pctl->groups[group].config;
241
242         return 0;
243 }
244
245 static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
246                                  unsigned group,
247                                  unsigned long config)
248 {
249         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
250         struct sunxi_pinctrl_group *g = &pctl->groups[group];
251         u32 val, mask;
252         u16 strength;
253         u8 dlevel;
254
255         switch (pinconf_to_config_param(config)) {
256         case PIN_CONFIG_DRIVE_STRENGTH:
257                 strength = pinconf_to_config_argument(config);
258                 if (strength > 40)
259                         return -EINVAL;
260                 /*
261                  * We convert from mA to what the register expects:
262                  *   0: 10mA
263                  *   1: 20mA
264                  *   2: 30mA
265                  *   3: 40mA
266                  */
267                 dlevel = strength / 10 - 1;
268                 val = readl(pctl->membase + sunxi_dlevel_reg(g->pin));
269                 mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(g->pin);
270                 writel((val & ~mask) | dlevel << sunxi_dlevel_offset(g->pin),
271                         pctl->membase + sunxi_dlevel_reg(g->pin));
272                 break;
273         case PIN_CONFIG_BIAS_PULL_UP:
274                 val = readl(pctl->membase + sunxi_pull_reg(g->pin));
275                 mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
276                 writel((val & ~mask) | 1 << sunxi_pull_offset(g->pin),
277                         pctl->membase + sunxi_pull_reg(g->pin));
278                 break;
279         case PIN_CONFIG_BIAS_PULL_DOWN:
280                 val = readl(pctl->membase + sunxi_pull_reg(g->pin));
281                 mask = PULL_PINS_MASK << sunxi_pull_offset(g->pin);
282                 writel((val & ~mask) | 2 << sunxi_pull_offset(g->pin),
283                         pctl->membase + sunxi_pull_reg(g->pin));
284                 break;
285         default:
286                 break;
287         }
288
289         /* cache the config value */
290         g->config = config;
291
292         return 0;
293 }
294
295 static struct pinconf_ops sunxi_pconf_ops = {
296         .pin_config_group_get   = sunxi_pconf_group_get,
297         .pin_config_group_set   = sunxi_pconf_group_set,
298 };
299
300 static int sunxi_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
301 {
302         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
303
304         return pctl->nfunctions;
305 }
306
307 static const char *sunxi_pmx_get_func_name(struct pinctrl_dev *pctldev,
308                                            unsigned function)
309 {
310         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
311
312         return pctl->functions[function].name;
313 }
314
315 static int sunxi_pmx_get_func_groups(struct pinctrl_dev *pctldev,
316                                      unsigned function,
317                                      const char * const **groups,
318                                      unsigned * const num_groups)
319 {
320         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
321
322         *groups = pctl->functions[function].groups;
323         *num_groups = pctl->functions[function].ngroups;
324
325         return 0;
326 }
327
328 static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
329                                  unsigned pin,
330                                  u8 config)
331 {
332         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
333
334         u32 val = readl(pctl->membase + sunxi_mux_reg(pin));
335         u32 mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
336         writel((val & ~mask) | config << sunxi_mux_offset(pin),
337                 pctl->membase + sunxi_mux_reg(pin));
338 }
339
340 static int sunxi_pmx_enable(struct pinctrl_dev *pctldev,
341                             unsigned function,
342                             unsigned group)
343 {
344         struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
345         struct sunxi_pinctrl_group *g = pctl->groups + group;
346         struct sunxi_pinctrl_function *func = pctl->functions + function;
347         struct sunxi_desc_function *desc =
348                 sunxi_pinctrl_desc_find_function_by_name(pctl,
349                                                          g->name,
350                                                          func->name);
351
352         if (!desc)
353                 return -EINVAL;
354
355         sunxi_pmx_set(pctldev, g->pin, desc->muxval);
356
357         return 0;
358 }
359
360 static struct pinmux_ops sunxi_pmx_ops = {
361         .get_functions_count    = sunxi_pmx_get_funcs_cnt,
362         .get_function_name      = sunxi_pmx_get_func_name,
363         .get_function_groups    = sunxi_pmx_get_func_groups,
364         .enable                 = sunxi_pmx_enable,
365 };
366
367 static struct pinctrl_desc sunxi_pctrl_desc = {
368         .confops        = &sunxi_pconf_ops,
369         .pctlops        = &sunxi_pctrl_ops,
370         .pmxops         = &sunxi_pmx_ops,
371 };
372
373 static struct of_device_id sunxi_pinctrl_match[] = {
374         {}
375 };
376 MODULE_DEVICE_TABLE(of, sunxi_pinctrl_match);
377
378 static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl,
379                                         const char *name)
380 {
381         struct sunxi_pinctrl_function *func = pctl->functions;
382
383         while (func->name) {
384                 /* function already there */
385                 if (strcmp(func->name, name) == 0) {
386                         func->ngroups++;
387                         return -EEXIST;
388                 }
389                 func++;
390         }
391
392         func->name = name;
393         func->ngroups = 1;
394
395         pctl->nfunctions++;
396
397         return 0;
398 }
399
400 static int sunxi_pinctrl_build_state(struct platform_device *pdev)
401 {
402         struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
403         int i;
404
405         pctl->ngroups = pctl->desc->npins;
406
407         /* Allocate groups */
408         pctl->groups = devm_kzalloc(&pdev->dev,
409                                     pctl->ngroups * sizeof(*pctl->groups),
410                                     GFP_KERNEL);
411         if (!pctl->groups)
412                 return -ENOMEM;
413
414         for (i = 0; i < pctl->desc->npins; i++) {
415                 const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
416                 struct sunxi_pinctrl_group *group = pctl->groups + i;
417
418                 group->name = pin->pin.name;
419                 group->pin = pin->pin.number;
420         }
421
422         /*
423          * We suppose that we won't have any more functions than pins,
424          * we'll reallocate that later anyway
425          */
426         pctl->functions = devm_kzalloc(&pdev->dev,
427                                 pctl->desc->npins * sizeof(*pctl->functions),
428                                 GFP_KERNEL);
429         if (!pctl->functions)
430                 return -ENOMEM;
431
432         /* Count functions and their associated groups */
433         for (i = 0; i < pctl->desc->npins; i++) {
434                 const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
435                 struct sunxi_desc_function *func = pin->functions;
436
437                 while (func->name) {
438                         sunxi_pinctrl_add_function(pctl, func->name);
439                         func++;
440                 }
441         }
442
443         pctl->functions = krealloc(pctl->functions,
444                                 pctl->nfunctions * sizeof(*pctl->functions),
445                                 GFP_KERNEL);
446
447         for (i = 0; i < pctl->desc->npins; i++) {
448                 const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
449                 struct sunxi_desc_function *func = pin->functions;
450
451                 while (func->name) {
452                         struct sunxi_pinctrl_function *func_item;
453                         const char **func_grp;
454
455                         func_item = sunxi_pinctrl_find_function_by_name(pctl,
456                                                                         func->name);
457                         if (!func_item)
458                                 return -EINVAL;
459
460                         if (!func_item->groups) {
461                                 func_item->groups =
462                                         devm_kzalloc(&pdev->dev,
463                                                      func_item->ngroups * sizeof(*func_item->groups),
464                                                      GFP_KERNEL);
465                                 if (!func_item->groups)
466                                         return -ENOMEM;
467                         }
468
469                         func_grp = func_item->groups;
470                         while (*func_grp)
471                                 func_grp++;
472
473                         *func_grp = pin->pin.name;
474                         func++;
475                 }
476         }
477
478         return 0;
479 }
480
481 static int sunxi_pinctrl_probe(struct platform_device *pdev)
482 {
483         struct device_node *node = pdev->dev.of_node;
484         const struct of_device_id *device;
485         struct pinctrl_pin_desc *pins;
486         struct sunxi_pinctrl *pctl;
487         int i, ret;
488
489         pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
490         if (!pctl)
491                 return -ENOMEM;
492         platform_set_drvdata(pdev, pctl);
493
494         pctl->membase = of_iomap(node, 0);
495         if (!pctl->membase)
496                 return -ENOMEM;
497
498         device = of_match_device(sunxi_pinctrl_match, &pdev->dev);
499         if (!device)
500                 return -ENODEV;
501
502         pctl->desc = (struct sunxi_pinctrl_desc *)device->data;
503
504         ret = sunxi_pinctrl_build_state(pdev);
505         if (ret) {
506                 dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
507                 return ret;
508         }
509
510         pins = devm_kzalloc(&pdev->dev,
511                             pctl->desc->npins * sizeof(*pins),
512                             GFP_KERNEL);
513         if (!pins)
514                 return -ENOMEM;
515
516         for (i = 0; i < pctl->desc->npins; i++)
517                 pins[i] = pctl->desc->pins[i].pin;
518
519         sunxi_pctrl_desc.name = dev_name(&pdev->dev);
520         sunxi_pctrl_desc.owner = THIS_MODULE;
521         sunxi_pctrl_desc.pins = pins;
522         sunxi_pctrl_desc.npins = pctl->desc->npins;
523         pctl->dev = &pdev->dev;
524         pctl->pctl_dev = pinctrl_register(&sunxi_pctrl_desc,
525                                           &pdev->dev, pctl);
526         if (!pctl->pctl_dev) {
527                 dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
528                 return -EINVAL;
529         }
530
531         dev_info(&pdev->dev, "initialized sunXi pin control driver\n");
532
533         return 0;
534 }
535
536 static struct platform_driver sunxi_pinctrl_driver = {
537         .probe = sunxi_pinctrl_probe,
538         .driver = {
539                 .name = "sunxi-pinctrl",
540                 .owner = THIS_MODULE,
541                 .of_match_table = sunxi_pinctrl_match,
542         },
543 };
544 module_platform_driver(sunxi_pinctrl_driver);
545
546 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
547 MODULE_DESCRIPTION("Allwinner A1X pinctrl driver");
548 MODULE_LICENSE("GPL");