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