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