xref: /OK3568_Linux_fs/u-boot/drivers/pinctrl/pinctrl-generic.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2015  Masahiro Yamada <yamada.masahiro@socionext.com>
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <dm.h>
9*4882a593Smuzhiyun #include <linux/compat.h>
10*4882a593Smuzhiyun #include <dm/pinctrl.h>
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun /**
13*4882a593Smuzhiyun  * pinctrl_pin_name_to_selector() - return the pin selector for a pin
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * @dev: pin controller device
16*4882a593Smuzhiyun  * @pin: the pin name to look up
17*4882a593Smuzhiyun  * @return: pin selector, or negative error code on failure
18*4882a593Smuzhiyun  */
pinctrl_pin_name_to_selector(struct udevice * dev,const char * pin)19*4882a593Smuzhiyun static int pinctrl_pin_name_to_selector(struct udevice *dev, const char *pin)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun 	const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
22*4882a593Smuzhiyun 	unsigned npins, selector;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	if (!ops->get_pins_count || !ops->get_pin_name) {
25*4882a593Smuzhiyun 		dev_dbg(dev, "get_pins_count or get_pin_name missing\n");
26*4882a593Smuzhiyun 		return -ENOSYS;
27*4882a593Smuzhiyun 	}
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	npins = ops->get_pins_count(dev);
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	/* See if this pctldev has this pin */
32*4882a593Smuzhiyun 	for (selector = 0; selector < npins; selector++) {
33*4882a593Smuzhiyun 		const char *pname = ops->get_pin_name(dev, selector);
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 		if (!strcmp(pin, pname))
36*4882a593Smuzhiyun 			return selector;
37*4882a593Smuzhiyun 	}
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	return -ENOSYS;
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /**
43*4882a593Smuzhiyun  * pinctrl_group_name_to_selector() - return the group selector for a group
44*4882a593Smuzhiyun  *
45*4882a593Smuzhiyun  * @dev: pin controller device
46*4882a593Smuzhiyun  * @group: the pin group name to look up
47*4882a593Smuzhiyun  * @return: pin group selector, or negative error code on failure
48*4882a593Smuzhiyun  */
pinctrl_group_name_to_selector(struct udevice * dev,const char * group)49*4882a593Smuzhiyun static int pinctrl_group_name_to_selector(struct udevice *dev,
50*4882a593Smuzhiyun 					  const char *group)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun 	const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
53*4882a593Smuzhiyun 	unsigned ngroups, selector;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	if (!ops->get_groups_count || !ops->get_group_name) {
56*4882a593Smuzhiyun 		dev_dbg(dev, "get_groups_count or get_group_name missing\n");
57*4882a593Smuzhiyun 		return -ENOSYS;
58*4882a593Smuzhiyun 	}
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	ngroups = ops->get_groups_count(dev);
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	/* See if this pctldev has this group */
63*4882a593Smuzhiyun 	for (selector = 0; selector < ngroups; selector++) {
64*4882a593Smuzhiyun 		const char *gname = ops->get_group_name(dev, selector);
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 		if (!strcmp(group, gname))
67*4882a593Smuzhiyun 			return selector;
68*4882a593Smuzhiyun 	}
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return -ENOSYS;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(PINMUX)
74*4882a593Smuzhiyun /**
75*4882a593Smuzhiyun  * pinmux_func_name_to_selector() - return the function selector for a function
76*4882a593Smuzhiyun  *
77*4882a593Smuzhiyun  * @dev: pin controller device
78*4882a593Smuzhiyun  * @function: the function name to look up
79*4882a593Smuzhiyun  * @return: function selector, or negative error code on failure
80*4882a593Smuzhiyun  */
pinmux_func_name_to_selector(struct udevice * dev,const char * function)81*4882a593Smuzhiyun static int pinmux_func_name_to_selector(struct udevice *dev,
82*4882a593Smuzhiyun 					const char *function)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
85*4882a593Smuzhiyun 	unsigned nfuncs, selector = 0;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (!ops->get_functions_count || !ops->get_function_name) {
88*4882a593Smuzhiyun 		dev_dbg(dev,
89*4882a593Smuzhiyun 			"get_functions_count or get_function_name missing\n");
90*4882a593Smuzhiyun 		return -ENOSYS;
91*4882a593Smuzhiyun 	}
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	nfuncs = ops->get_functions_count(dev);
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	/* See if this pctldev has this function */
96*4882a593Smuzhiyun 	for (selector = 0; selector < nfuncs; selector++) {
97*4882a593Smuzhiyun 		const char *fname = ops->get_function_name(dev, selector);
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 		if (!strcmp(function, fname))
100*4882a593Smuzhiyun 			return selector;
101*4882a593Smuzhiyun 	}
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	return -ENOSYS;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /**
107*4882a593Smuzhiyun  * pinmux_enable_setting() - enable pin-mux setting for a certain pin/group
108*4882a593Smuzhiyun  *
109*4882a593Smuzhiyun  * @dev: pin controller device
110*4882a593Smuzhiyun  * @is_group: target of operation (true: pin group, false: pin)
111*4882a593Smuzhiyun  * @selector: pin selector or group selector, depending on @is_group
112*4882a593Smuzhiyun  * @func_selector: function selector
113*4882a593Smuzhiyun  * @return: 0 on success, or negative error code on failure
114*4882a593Smuzhiyun  */
pinmux_enable_setting(struct udevice * dev,bool is_group,unsigned selector,unsigned func_selector)115*4882a593Smuzhiyun static int pinmux_enable_setting(struct udevice *dev, bool is_group,
116*4882a593Smuzhiyun 				 unsigned selector, unsigned func_selector)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	if (is_group) {
121*4882a593Smuzhiyun 		if (!ops->pinmux_group_set) {
122*4882a593Smuzhiyun 			dev_dbg(dev, "pinmux_group_set op missing\n");
123*4882a593Smuzhiyun 			return -ENOSYS;
124*4882a593Smuzhiyun 		}
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 		return ops->pinmux_group_set(dev, selector, func_selector);
127*4882a593Smuzhiyun 	} else {
128*4882a593Smuzhiyun 		if (!ops->pinmux_set) {
129*4882a593Smuzhiyun 			dev_dbg(dev, "pinmux_set op missing\n");
130*4882a593Smuzhiyun 			return -ENOSYS;
131*4882a593Smuzhiyun 		}
132*4882a593Smuzhiyun 		return ops->pinmux_set(dev, selector, func_selector);
133*4882a593Smuzhiyun 	}
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun #else
pinmux_func_name_to_selector(struct udevice * dev,const char * function)136*4882a593Smuzhiyun static int pinmux_func_name_to_selector(struct udevice *dev,
137*4882a593Smuzhiyun 					const char *function)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	return 0;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
pinmux_enable_setting(struct udevice * dev,bool is_group,unsigned selector,unsigned func_selector)142*4882a593Smuzhiyun static int pinmux_enable_setting(struct udevice *dev, bool is_group,
143*4882a593Smuzhiyun 				 unsigned selector, unsigned func_selector)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	return 0;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun #endif
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(PINCONF)
150*4882a593Smuzhiyun /**
151*4882a593Smuzhiyun  * pinconf_prop_name_to_param() - return parameter ID for a property name
152*4882a593Smuzhiyun  *
153*4882a593Smuzhiyun  * @dev: pin controller device
154*4882a593Smuzhiyun  * @property: property name in DTS, such as "bias-pull-up", "slew-rate", etc.
155*4882a593Smuzhiyun  * @default_value: return default value in case no value is specified in DTS
156*4882a593Smuzhiyun  * @return: return pamater ID, or negative error code on failure
157*4882a593Smuzhiyun  */
pinconf_prop_name_to_param(struct udevice * dev,const char * property,u32 * default_value)158*4882a593Smuzhiyun static int pinconf_prop_name_to_param(struct udevice *dev,
159*4882a593Smuzhiyun 				      const char *property, u32 *default_value)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
162*4882a593Smuzhiyun 	const struct pinconf_param *p, *end;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	if (!ops->pinconf_num_params || !ops->pinconf_params) {
165*4882a593Smuzhiyun 		dev_dbg(dev, "pinconf_num_params or pinconf_params missing\n");
166*4882a593Smuzhiyun 		return -ENOSYS;
167*4882a593Smuzhiyun 	}
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	p = ops->pinconf_params;
170*4882a593Smuzhiyun 	end = p + ops->pinconf_num_params;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	/* See if this pctldev supports this parameter */
173*4882a593Smuzhiyun 	for (; p < end; p++) {
174*4882a593Smuzhiyun 		if (!strcmp(property, p->property)) {
175*4882a593Smuzhiyun 			*default_value = p->default_value;
176*4882a593Smuzhiyun 			return p->param;
177*4882a593Smuzhiyun 		}
178*4882a593Smuzhiyun 	}
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	return -ENOSYS;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun /**
184*4882a593Smuzhiyun  * pinconf_enable_setting() - apply pin configuration for a certain pin/group
185*4882a593Smuzhiyun  *
186*4882a593Smuzhiyun  * @dev: pin controller device
187*4882a593Smuzhiyun  * @is_group: target of operation (true: pin group, false: pin)
188*4882a593Smuzhiyun  * @selector: pin selector or group selector, depending on @is_group
189*4882a593Smuzhiyun  * @param: configuration paramter
190*4882a593Smuzhiyun  * @argument: argument taken by some configuration parameters
191*4882a593Smuzhiyun  * @return: 0 on success, or negative error code on failure
192*4882a593Smuzhiyun  */
pinconf_enable_setting(struct udevice * dev,bool is_group,unsigned selector,unsigned param,u32 argument)193*4882a593Smuzhiyun static int pinconf_enable_setting(struct udevice *dev, bool is_group,
194*4882a593Smuzhiyun 				  unsigned selector, unsigned param,
195*4882a593Smuzhiyun 				  u32 argument)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	if (is_group) {
200*4882a593Smuzhiyun 		if (!ops->pinconf_group_set) {
201*4882a593Smuzhiyun 			dev_dbg(dev, "pinconf_group_set op missing\n");
202*4882a593Smuzhiyun 			return -ENOSYS;
203*4882a593Smuzhiyun 		}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 		return ops->pinconf_group_set(dev, selector, param,
206*4882a593Smuzhiyun 					      argument);
207*4882a593Smuzhiyun 	} else {
208*4882a593Smuzhiyun 		if (!ops->pinconf_set) {
209*4882a593Smuzhiyun 			dev_dbg(dev, "pinconf_set op missing\n");
210*4882a593Smuzhiyun 			return -ENOSYS;
211*4882a593Smuzhiyun 		}
212*4882a593Smuzhiyun 		return ops->pinconf_set(dev, selector, param, argument);
213*4882a593Smuzhiyun 	}
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun #else
pinconf_prop_name_to_param(struct udevice * dev,const char * property,u32 * default_value)216*4882a593Smuzhiyun static int pinconf_prop_name_to_param(struct udevice *dev,
217*4882a593Smuzhiyun 				      const char *property, u32 *default_value)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	return -ENOSYS;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
pinconf_enable_setting(struct udevice * dev,bool is_group,unsigned selector,unsigned param,u32 argument)222*4882a593Smuzhiyun static int pinconf_enable_setting(struct udevice *dev, bool is_group,
223*4882a593Smuzhiyun 				  unsigned selector, unsigned param,
224*4882a593Smuzhiyun 				  u32 argument)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun 	return 0;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun #endif
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun /**
231*4882a593Smuzhiyun  * pinctrl_generic_set_state_one() - set state for a certain pin/group
232*4882a593Smuzhiyun  * Apply all pin multiplexing and pin configurations specified by @config
233*4882a593Smuzhiyun  * for a given pin or pin group.
234*4882a593Smuzhiyun  *
235*4882a593Smuzhiyun  * @dev: pin controller device
236*4882a593Smuzhiyun  * @config: pseudo device pointing to config node
237*4882a593Smuzhiyun  * @is_group: target of operation (true: pin group, false: pin)
238*4882a593Smuzhiyun  * @selector: pin selector or group selector, depending on @is_group
239*4882a593Smuzhiyun  * @return: 0 on success, or negative error code on failure
240*4882a593Smuzhiyun  */
pinctrl_generic_set_state_one(struct udevice * dev,struct udevice * config,bool is_group,unsigned selector)241*4882a593Smuzhiyun static int pinctrl_generic_set_state_one(struct udevice *dev,
242*4882a593Smuzhiyun 					 struct udevice *config,
243*4882a593Smuzhiyun 					 bool is_group, unsigned selector)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	const char *propname;
246*4882a593Smuzhiyun 	const void *value;
247*4882a593Smuzhiyun 	struct ofprop property;
248*4882a593Smuzhiyun 	int len, func_selector, param, ret;
249*4882a593Smuzhiyun 	u32 arg, default_val;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	dev_for_each_property(property, config) {
252*4882a593Smuzhiyun 		value = dev_read_prop_by_prop(&property, &propname, &len);
253*4882a593Smuzhiyun 		if (!value)
254*4882a593Smuzhiyun 			return -EINVAL;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 		if (!strcmp(propname, "function")) {
257*4882a593Smuzhiyun 			func_selector = pinmux_func_name_to_selector(dev,
258*4882a593Smuzhiyun 								     value);
259*4882a593Smuzhiyun 			if (func_selector < 0)
260*4882a593Smuzhiyun 				return func_selector;
261*4882a593Smuzhiyun 			ret = pinmux_enable_setting(dev, is_group,
262*4882a593Smuzhiyun 						    selector,
263*4882a593Smuzhiyun 						    func_selector);
264*4882a593Smuzhiyun 		} else {
265*4882a593Smuzhiyun 			param = pinconf_prop_name_to_param(dev, propname,
266*4882a593Smuzhiyun 							   &default_val);
267*4882a593Smuzhiyun 			if (param < 0)
268*4882a593Smuzhiyun 				continue; /* just skip unknown properties */
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 			if (len >= sizeof(fdt32_t))
271*4882a593Smuzhiyun 				arg = fdt32_to_cpu(*(fdt32_t *)value);
272*4882a593Smuzhiyun 			else
273*4882a593Smuzhiyun 				arg = default_val;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 			ret = pinconf_enable_setting(dev, is_group,
276*4882a593Smuzhiyun 						     selector, param, arg);
277*4882a593Smuzhiyun 		}
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 		if (ret)
280*4882a593Smuzhiyun 			return ret;
281*4882a593Smuzhiyun 	}
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	return 0;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /**
287*4882a593Smuzhiyun  * pinctrl_generic_set_state_subnode() - apply all settings in config node
288*4882a593Smuzhiyun  *
289*4882a593Smuzhiyun  * @dev: pin controller device
290*4882a593Smuzhiyun  * @config: pseudo device pointing to config node
291*4882a593Smuzhiyun  * @return: 0 on success, or negative error code on failure
292*4882a593Smuzhiyun  */
pinctrl_generic_set_state_subnode(struct udevice * dev,struct udevice * config)293*4882a593Smuzhiyun static int pinctrl_generic_set_state_subnode(struct udevice *dev,
294*4882a593Smuzhiyun 					     struct udevice *config)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	const char *subnode_target_type = "pins";
297*4882a593Smuzhiyun 	bool is_group = false;
298*4882a593Smuzhiyun 	const char *name;
299*4882a593Smuzhiyun 	int strings_count, selector, i, ret;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	strings_count = dev_read_string_count(config, subnode_target_type);
302*4882a593Smuzhiyun 	if (strings_count < 0) {
303*4882a593Smuzhiyun 		subnode_target_type = "groups";
304*4882a593Smuzhiyun 		is_group = true;
305*4882a593Smuzhiyun 		strings_count = dev_read_string_count(config,
306*4882a593Smuzhiyun 						      subnode_target_type);
307*4882a593Smuzhiyun 		if (strings_count < 0) {
308*4882a593Smuzhiyun 			/* skip this node; may contain config child nodes */
309*4882a593Smuzhiyun 			return 0;
310*4882a593Smuzhiyun 		}
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	for (i = 0; i < strings_count; i++) {
314*4882a593Smuzhiyun 		ret = dev_read_string_index(config, subnode_target_type, i,
315*4882a593Smuzhiyun 					    &name);
316*4882a593Smuzhiyun 		if (ret)
317*4882a593Smuzhiyun 			return ret;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 		if (is_group)
320*4882a593Smuzhiyun 			selector = pinctrl_group_name_to_selector(dev, name);
321*4882a593Smuzhiyun 		else
322*4882a593Smuzhiyun 			selector = pinctrl_pin_name_to_selector(dev, name);
323*4882a593Smuzhiyun 		if (selector < 0)
324*4882a593Smuzhiyun 			return selector;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 		ret = pinctrl_generic_set_state_one(dev, config,
327*4882a593Smuzhiyun 						    is_group, selector);
328*4882a593Smuzhiyun 		if (ret)
329*4882a593Smuzhiyun 			return ret;
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	return 0;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun 
pinctrl_generic_set_state(struct udevice * dev,struct udevice * config)335*4882a593Smuzhiyun int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	struct udevice *child;
338*4882a593Smuzhiyun 	int ret;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	ret = pinctrl_generic_set_state_subnode(dev, config);
341*4882a593Smuzhiyun 	if (ret)
342*4882a593Smuzhiyun 		return ret;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	for (device_find_first_child(config, &child);
345*4882a593Smuzhiyun 	     child;
346*4882a593Smuzhiyun 	     device_find_next_child(&child)) {
347*4882a593Smuzhiyun 		ret = pinctrl_generic_set_state_subnode(dev, child);
348*4882a593Smuzhiyun 		if (ret)
349*4882a593Smuzhiyun 			return ret;
350*4882a593Smuzhiyun 	}
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	return 0;
353*4882a593Smuzhiyun }
354