xref: /linux/drivers/pinctrl/pinctrl-generic.c (revision 23b0f90ba871f096474e1c27c3d14f455189d2d9)
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 
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  */
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