1 // SPDX-License-Identifier: GPL-2.0-only
2
3 #define pr_fmt(fmt) "generic pinconfig core: " fmt
4
5 #include <linux/array_size.h>
6 #include <linux/device.h>
7 #include <linux/module.h>
8 #include <linux/of.h>
9 #include <linux/slab.h>
10
11 #include <linux/pinctrl/pinconf-generic.h>
12 #include <linux/pinctrl/pinconf.h>
13 #include <linux/pinctrl/pinctrl.h>
14
15 #include "core.h"
16 #include "pinconf.h"
17 #include "pinctrl-utils.h"
18 #include "pinmux.h"
19
pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev * pctldev,struct device_node * parent,struct device_node * np,struct pinctrl_map ** maps,unsigned int * num_maps,unsigned int * num_reserved_maps,const char ** group_names,unsigned int ngroups)20 static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev,
21 struct device_node *parent,
22 struct device_node *np,
23 struct pinctrl_map **maps,
24 unsigned int *num_maps,
25 unsigned int *num_reserved_maps,
26 const char **group_names,
27 unsigned int ngroups)
28 {
29 struct device *dev = pctldev->dev;
30 const char **functions;
31 const char *group_name;
32 unsigned long *configs;
33 unsigned int num_configs, pin, *pins;
34 int npins, ret, reserve = 1;
35
36 npins = of_property_count_u32_elems(np, "pins");
37
38 if (npins < 1) {
39 dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n",
40 parent, np, npins);
41 return npins;
42 }
43
44 group_name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", parent, np);
45 if (!group_name)
46 return -ENOMEM;
47
48 group_names[ngroups] = group_name;
49
50 pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
51 if (!pins)
52 return -ENOMEM;
53
54 functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL);
55 if (!functions)
56 return -ENOMEM;
57
58 for (int i = 0; i < npins; i++) {
59 ret = of_property_read_u32_index(np, "pins", i, &pin);
60 if (ret)
61 return ret;
62
63 pins[i] = pin;
64
65 ret = of_property_read_string(np, "function", &functions[i]);
66 if (ret)
67 return ret;
68 }
69
70 ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve);
71 if (ret)
72 return ret;
73
74 ret = pinctrl_utils_add_map_mux(pctldev, maps, num_reserved_maps, num_maps, group_name,
75 parent->name);
76 if (ret < 0)
77 return ret;
78
79 ret = pinctrl_generic_add_group(pctldev, group_name, pins, npins, functions);
80 if (ret < 0)
81 return dev_err_probe(dev, ret, "failed to add group %s: %d\n",
82 group_name, ret);
83
84 ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs);
85 if (ret)
86 return dev_err_probe(dev, ret, "failed to parse pin config of group %s\n",
87 group_name);
88
89 if (num_configs == 0)
90 return 0;
91
92 ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve);
93 if (ret)
94 return ret;
95
96 ret = pinctrl_utils_add_map_configs(pctldev, maps, num_reserved_maps, num_maps, group_name,
97 configs,
98 num_configs, PIN_MAP_TYPE_CONFIGS_GROUP);
99 kfree(configs);
100 if (ret)
101 return ret;
102
103 return 0;
104 };
105
106 /*
107 * For platforms that do not define groups or functions in the driver, but
108 * instead use the devicetree to describe them. This function will, unlike
109 * pinconf_generic_dt_node_to_map() etc which rely on driver defined groups
110 * and functions, create them in addition to parsing pinconf properties and
111 * adding mappings.
112 */
pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev * pctldev,struct device_node * np,struct pinctrl_map ** maps,unsigned int * num_maps)113 int pinctrl_generic_pins_function_dt_node_to_map(struct pinctrl_dev *pctldev,
114 struct device_node *np,
115 struct pinctrl_map **maps,
116 unsigned int *num_maps)
117 {
118 struct device *dev = pctldev->dev;
119 struct device_node *child_np;
120 const char **group_names;
121 unsigned int num_reserved_maps = 0;
122 int ngroups = 0;
123 int ret;
124
125 *maps = NULL;
126 *num_maps = 0;
127
128 /*
129 * Check if this is actually the pins node, or a parent containing
130 * multiple pins nodes.
131 */
132 if (!of_property_present(np, "pins"))
133 goto parent;
134
135 group_names = devm_kcalloc(dev, 1, sizeof(*group_names), GFP_KERNEL);
136 if (!group_names)
137 return -ENOMEM;
138
139 ret = pinctrl_generic_pins_function_dt_subnode_to_map(pctldev, np, np,
140 maps, num_maps,
141 &num_reserved_maps,
142 group_names,
143 ngroups);
144 if (ret) {
145 pinctrl_utils_free_map(pctldev, *maps, *num_maps);
146 return dev_err_probe(dev, ret, "error figuring out mappings for %s\n", np->name);
147 }
148
149 ret = pinmux_generic_add_function(pctldev, np->name, group_names, 1, NULL);
150 if (ret < 0) {
151 pinctrl_utils_free_map(pctldev, *maps, *num_maps);
152 return dev_err_probe(dev, ret, "error adding function %s\n", np->name);
153 }
154
155 return 0;
156
157 parent:
158 for_each_available_child_of_node(np, child_np)
159 ngroups += 1;
160
161 group_names = devm_kcalloc(dev, ngroups, sizeof(*group_names), GFP_KERNEL);
162 if (!group_names)
163 return -ENOMEM;
164
165 ngroups = 0;
166 for_each_available_child_of_node_scoped(np, child_np) {
167 ret = pinctrl_generic_pins_function_dt_subnode_to_map(pctldev, np, child_np,
168 maps, num_maps,
169 &num_reserved_maps,
170 group_names,
171 ngroups);
172 if (ret) {
173 pinctrl_utils_free_map(pctldev, *maps, *num_maps);
174 return dev_err_probe(dev, ret, "error figuring out mappings for %s\n",
175 np->name);
176 }
177
178 ngroups++;
179 }
180
181 ret = pinmux_generic_add_function(pctldev, np->name, group_names, ngroups, NULL);
182 if (ret < 0) {
183 pinctrl_utils_free_map(pctldev, *maps, *num_maps);
184 return dev_err_probe(dev, ret, "error adding function %s\n", np->name);
185 }
186
187 return 0;
188 }
189 EXPORT_SYMBOL_GPL(pinctrl_generic_pins_function_dt_node_to_map);
190