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