Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / pinctrl / berlin / berlin.c
1 /*
2  * Marvell Berlin SoC pinctrl core driver
3  *
4  * Copyright (C) 2014 Marvell Technology Group Ltd.
5  *
6  * Antoine Ténart <antoine.tenart@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/pinctrl.h>
19 #include <linux/pinctrl/pinmux.h>
20 #include <linux/platform_device.h>
21 #include <linux/regmap.h>
22 #include <linux/slab.h>
23
24 #include "../core.h"
25 #include "../pinctrl-utils.h"
26 #include "berlin.h"
27
28 struct berlin_pinctrl {
29         struct regmap *regmap;
30         struct device *dev;
31         const struct berlin_pinctrl_desc *desc;
32         struct berlin_pinctrl_function *functions;
33         unsigned nfunctions;
34         struct pinctrl_dev *pctrl_dev;
35 };
36
37 static int berlin_pinctrl_get_group_count(struct pinctrl_dev *pctrl_dev)
38 {
39         struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
40
41         return pctrl->desc->ngroups;
42 }
43
44 static const char *berlin_pinctrl_get_group_name(struct pinctrl_dev *pctrl_dev,
45                                                  unsigned group)
46 {
47         struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
48
49         return pctrl->desc->groups[group].name;
50 }
51
52 static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev,
53                                          struct device_node *node,
54                                          struct pinctrl_map **map,
55                                          unsigned *num_maps)
56 {
57         struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
58         struct property *prop;
59         const char *function_name, *group_name;
60         unsigned reserved_maps = 0;
61         int ret, ngroups;
62
63         *map = NULL;
64         *num_maps = 0;
65
66         ret = of_property_read_string(node, "function", &function_name);
67         if (ret) {
68                 dev_err(pctrl->dev,
69                         "missing function property in node %s\n",
70                         node->name);
71                 return -EINVAL;
72         }
73
74         ngroups = of_property_count_strings(node, "groups");
75         if (ngroups < 0) {
76                 dev_err(pctrl->dev,
77                         "missing groups property in node %s\n",
78                         node->name);
79                 return -EINVAL;
80         }
81
82         ret = pinctrl_utils_reserve_map(pctrl_dev, map, &reserved_maps,
83                                         num_maps, ngroups);
84         if (ret) {
85                 dev_err(pctrl->dev, "can't reserve map: %d\n", ret);
86                 return ret;
87         }
88
89         of_property_for_each_string(node, "groups", prop, group_name) {
90                 ret = pinctrl_utils_add_map_mux(pctrl_dev, map, &reserved_maps,
91                                                 num_maps, group_name,
92                                                 function_name);
93                 if (ret) {
94                         dev_err(pctrl->dev, "can't add map: %d\n", ret);
95                         return ret;
96                 }
97         }
98
99         return 0;
100 }
101
102 static const struct pinctrl_ops berlin_pinctrl_ops = {
103         .get_groups_count       = &berlin_pinctrl_get_group_count,
104         .get_group_name         = &berlin_pinctrl_get_group_name,
105         .dt_node_to_map         = &berlin_pinctrl_dt_node_to_map,
106         .dt_free_map            = &pinctrl_utils_dt_free_map,
107 };
108
109 static int berlin_pinmux_get_functions_count(struct pinctrl_dev *pctrl_dev)
110 {
111         struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
112
113         return pctrl->nfunctions;
114 }
115
116 static const char *berlin_pinmux_get_function_name(struct pinctrl_dev *pctrl_dev,
117                                                    unsigned function)
118 {
119         struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
120
121         return pctrl->functions[function].name;
122 }
123
124 static int berlin_pinmux_get_function_groups(struct pinctrl_dev *pctrl_dev,
125                                              unsigned function,
126                                              const char * const **groups,
127                                              unsigned * const num_groups)
128 {
129         struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
130
131         *groups = pctrl->functions[function].groups;
132         *num_groups = pctrl->functions[function].ngroups;
133
134         return 0;
135 }
136
137 static struct berlin_desc_function *
138 berlin_pinctrl_find_function_by_name(struct berlin_pinctrl *pctrl,
139                                      const struct berlin_desc_group *group,
140                                      const char *fname)
141 {
142         struct berlin_desc_function *function = group->functions;
143
144         while (function->name) {
145                 if (!strcmp(function->name, fname))
146                         return function;
147
148                 function++;
149         }
150
151         return NULL;
152 }
153
154 static int berlin_pinmux_set(struct pinctrl_dev *pctrl_dev,
155                              unsigned function,
156                              unsigned group)
157 {
158         struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev);
159         const struct berlin_desc_group *group_desc = pctrl->desc->groups + group;
160         struct berlin_pinctrl_function *func = pctrl->functions + function;
161         struct berlin_desc_function *function_desc =
162                 berlin_pinctrl_find_function_by_name(pctrl, group_desc,
163                                                      func->name);
164         u32 mask, val;
165
166         if (!function_desc)
167                 return -EINVAL;
168
169         mask = GENMASK(group_desc->lsb + group_desc->bit_width - 1,
170                        group_desc->lsb);
171         val = function_desc->muxval << group_desc->lsb;
172         regmap_update_bits(pctrl->regmap, group_desc->offset, mask, val);
173
174         return 0;
175 }
176
177 static const struct pinmux_ops berlin_pinmux_ops = {
178         .get_functions_count    = &berlin_pinmux_get_functions_count,
179         .get_function_name      = &berlin_pinmux_get_function_name,
180         .get_function_groups    = &berlin_pinmux_get_function_groups,
181         .set_mux                = &berlin_pinmux_set,
182 };
183
184 static int berlin_pinctrl_add_function(struct berlin_pinctrl *pctrl,
185                                        const char *name)
186 {
187         struct berlin_pinctrl_function *function = pctrl->functions;
188
189         while (function->name) {
190                 if (!strcmp(function->name, name)) {
191                         function->ngroups++;
192                         return -EEXIST;
193                 }
194                 function++;
195         }
196
197         function->name = name;
198         function->ngroups = 1;
199
200         pctrl->nfunctions++;
201
202         return 0;
203 }
204
205 static int berlin_pinctrl_build_state(struct platform_device *pdev)
206 {
207         struct berlin_pinctrl *pctrl = platform_get_drvdata(pdev);
208         struct berlin_desc_group const *desc_group;
209         struct berlin_desc_function const *desc_function;
210         int i, max_functions = 0;
211
212         pctrl->nfunctions = 0;
213
214         for (i = 0; i < pctrl->desc->ngroups; i++) {
215                 desc_group = pctrl->desc->groups + i;
216                 /* compute the maxiumum number of functions a group can have */
217                 max_functions += 1 << (desc_group->bit_width + 1);
218         }
219
220         /* we will reallocate later */
221         pctrl->functions = devm_kzalloc(&pdev->dev,
222                                         max_functions * sizeof(*pctrl->functions),
223                                         GFP_KERNEL);
224         if (!pctrl->functions)
225                 return -ENOMEM;
226
227         /* register all functions */
228         for (i = 0; i < pctrl->desc->ngroups; i++) {
229                 desc_group = pctrl->desc->groups + i;
230                 desc_function = desc_group->functions;
231
232                 while (desc_function->name) {
233                         berlin_pinctrl_add_function(pctrl, desc_function->name);
234                         desc_function++;
235                 }
236         }
237
238         pctrl->functions = krealloc(pctrl->functions,
239                                     pctrl->nfunctions * sizeof(*pctrl->functions),
240                                     GFP_KERNEL);
241
242         /* map functions to theirs groups */
243         for (i = 0; i < pctrl->desc->ngroups; i++) {
244                 desc_group = pctrl->desc->groups + i;
245                 desc_function = desc_group->functions;
246
247                 while (desc_function->name) {
248                         struct berlin_pinctrl_function
249                                 *function = pctrl->functions;
250                         const char **groups;
251                         bool found = false;
252
253                         while (function->name) {
254                                 if (!strcmp(desc_function->name, function->name)) {
255                                         found = true;
256                                         break;
257                                 }
258                                 function++;
259                         }
260
261                         if (!found)
262                                 return -EINVAL;
263
264                         if (!function->groups) {
265                                 function->groups =
266                                         devm_kzalloc(&pdev->dev,
267                                                      function->ngroups * sizeof(char *),
268                                                      GFP_KERNEL);
269
270                                 if (!function->groups)
271                                         return -ENOMEM;
272                         }
273
274                         groups = function->groups;
275                         while (*groups)
276                                 groups++;
277
278                         *groups = desc_group->name;
279
280                         desc_function++;
281                 }
282         }
283
284         return 0;
285 }
286
287 static struct pinctrl_desc berlin_pctrl_desc = {
288         .name           = "berlin-pinctrl",
289         .pctlops        = &berlin_pinctrl_ops,
290         .pmxops         = &berlin_pinmux_ops,
291         .owner          = THIS_MODULE,
292 };
293
294 int berlin_pinctrl_probe(struct platform_device *pdev,
295                          const struct berlin_pinctrl_desc *desc)
296 {
297         struct device *dev = &pdev->dev;
298         struct berlin_pinctrl *pctrl;
299         struct regmap *regmap;
300         int ret;
301
302         regmap = dev_get_regmap(&pdev->dev, NULL);
303         if (!regmap)
304                 return -ENODEV;
305
306         pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
307         if (!pctrl)
308                 return -ENOMEM;
309
310         platform_set_drvdata(pdev, pctrl);
311
312         pctrl->regmap = regmap;
313         pctrl->dev = &pdev->dev;
314         pctrl->desc = desc;
315
316         ret = berlin_pinctrl_build_state(pdev);
317         if (ret) {
318                 dev_err(dev, "cannot build driver state: %d\n", ret);
319                 return ret;
320         }
321
322         pctrl->pctrl_dev = pinctrl_register(&berlin_pctrl_desc, dev, pctrl);
323         if (!pctrl->pctrl_dev) {
324                 dev_err(dev, "failed to register pinctrl driver\n");
325                 return -EINVAL;
326         }
327
328         return 0;
329 }