1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2015  Masahiro Yamada <yamada.masahiro@socionext.com>
4 */
5
6#include <common.h>
7#include <dm.h>
8#include <dm/device_compat.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 */
19static 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 */
49static 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 */
81static 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 */
115static 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
136static int pinmux_func_name_to_selector(struct udevice *dev,
137					const char *function)
138{
139	return 0;
140}
141
142static 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 */
158static 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 */
193static 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
216static int pinconf_prop_name_to_param(struct udevice *dev,
217				      const char *property, u32 *default_value)
218{
219	return -ENOSYS;
220}
221
222static 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
230enum pinmux_subnode_type {
231	PST_NONE = 0,
232	PST_PIN,
233	PST_GROUP,
234	PST_PINMUX,
235};
236
237static const char *alloc_name_with_prefix(const char *name, const char *prefix)
238{
239	if (prefix) {
240		char *name_with_prefix = malloc(strlen(prefix) + strlen(name) + 1);
241		if (name_with_prefix)
242			sprintf(name_with_prefix, "%s%s", prefix, name);
243		return name_with_prefix;
244	} else {
245		return name;
246	}
247}
248
249static void free_name_with_prefix(const char *name_with_prefix, const char *prefix)
250{
251	if (prefix)
252		free((char *)name_with_prefix);
253}
254
255/**
256 * pinctrl_generic_set_state_one() - set state for a certain pin/group
257 * Apply all pin multiplexing and pin configurations specified by @config
258 * for a given pin or pin group.
259 *
260 * @dev: pin controller device
261 * @config: pseudo device pointing to config node
262 * @subnode_type: target of operation (pin, group, or pin specified by a pinmux
263 * group)
264 * @selector: pin selector or group selector, depending on @subnode_type
265 * @return: 0 on success, or negative error code on failure
266 */
267static int pinctrl_generic_set_state_one(struct udevice *dev,
268					 struct udevice *config,
269					 const char *prefix,
270					 enum pinmux_subnode_type subnode_type,
271					 unsigned selector)
272{
273	const char *function_propname;
274	const char *propname;
275	const void *value;
276	struct ofprop property;
277	int len, func_selector, param, ret;
278	u32 arg, default_val;
279
280	assert(subnode_type != PST_NONE);
281
282	function_propname = alloc_name_with_prefix("function", prefix);
283	if (!function_propname)
284		return -ENOMEM;
285
286	dev_for_each_property(property, config) {
287		value = dev_read_prop_by_prop(&property, &propname, &len);
288		if (!value) {
289			free_name_with_prefix(function_propname, prefix);
290			return -EINVAL;
291		}
292
293		/* pinmux subnodes already have their muxing set */
294		if (subnode_type != PST_PINMUX &&
295		    !strcmp(propname, function_propname)) {
296			func_selector = pinmux_func_name_to_selector(dev,
297								     value);
298			if (func_selector < 0) {
299				free_name_with_prefix(function_propname, prefix);
300				return func_selector;
301			}
302			ret = pinmux_enable_setting(dev,
303						    subnode_type == PST_GROUP,
304						    selector,
305						    func_selector);
306		} else {
307			param = pinconf_prop_name_to_param(dev, propname,
308							   &default_val);
309			if (param < 0)
310				continue; /* just skip unknown properties */
311
312			if (len >= sizeof(fdt32_t))
313				arg = fdt32_to_cpu(*(fdt32_t *)value);
314			else
315				arg = default_val;
316
317			ret = pinconf_enable_setting(dev,
318						     subnode_type == PST_GROUP,
319						     selector, param, arg);
320		}
321
322		if (ret) {
323			free_name_with_prefix(function_propname, prefix);
324			return ret;
325		}
326	}
327
328	free_name_with_prefix(function_propname, prefix);
329	return 0;
330}
331
332/**
333 * pinctrl_generic_get_subnode_type() - determine whether there is a valid
334 * pins, groups, or pinmux property in the config node
335 *
336 * @dev: pin controller device
337 * @config: pseudo device pointing to config node
338 * @count: number of specifiers contained within the property
339 * @return: the type of the subnode, or PST_NONE
340 */
341static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev,
342								 struct udevice *config,
343								 const char *prefix,
344								 int *count)
345{
346	const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
347	const char *propname;
348
349	propname = alloc_name_with_prefix("pins", prefix);
350	if (!propname)
351		return -ENOMEM;
352	*count = dev_read_string_count(config, propname);
353	free_name_with_prefix(propname, prefix);
354	if (*count >= 0)
355		return PST_PIN;
356
357	propname = alloc_name_with_prefix("groups", prefix);
358	if (!propname)
359		return -ENOMEM;
360	*count = dev_read_string_count(config, propname);
361	free_name_with_prefix(propname, prefix);
362	if (*count >= 0)
363		return PST_GROUP;
364
365	if (ops->pinmux_property_set) {
366		propname = alloc_name_with_prefix("pinmux", prefix);
367		if (!propname)
368			return -ENOMEM;
369		*count = dev_read_size(config, propname);
370		free_name_with_prefix(propname, prefix);
371		if (*count >= 0 && !(*count % sizeof(u32))) {
372			*count /= sizeof(u32);
373			return PST_PINMUX;
374		}
375	}
376
377	*count = 0;
378	return PST_NONE;
379}
380
381/**
382 * pinctrl_generic_set_state_subnode() - apply all settings in config node
383 *
384 * @dev: pin controller device
385 * @config: pseudo device pointing to config node
386 * @prefix: device tree property prefix (e.g. vendor specific)
387 * @return: 0 on success, or negative error code on failure
388 */
389static int pinctrl_generic_set_state_subnode(struct udevice *dev,
390					     struct udevice *config,
391					     const char *prefix)
392{
393	enum pinmux_subnode_type subnode_type;
394	const char *propname;
395	const char *name;
396	int count, selector, i, ret, scratch;
397	const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */
398
399	subnode_type = pinctrl_generic_get_subnode_type(dev, config, prefix, &count);
400
401	debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name,
402	      count);
403
404	if (subnode_type == PST_PINMUX) {
405		propname = alloc_name_with_prefix("pinmux", prefix);
406		if (!propname)
407			return -ENOMEM;
408		pinmux_groups = dev_read_prop(config, propname, &scratch);
409		free_name_with_prefix(propname, prefix);
410		if (!pinmux_groups)
411			return -EINVAL;
412	}
413
414	for (i = 0; i < count; i++) {
415		switch (subnode_type) {
416		case PST_PIN:
417			propname = alloc_name_with_prefix("pins", prefix);
418			if (!propname)
419				return -ENOMEM;
420			ret = dev_read_string_index(config, propname, i, &name);
421			free_name_with_prefix(propname, prefix);
422			if (ret)
423				return ret;
424			selector = pinctrl_pin_name_to_selector(dev, name);
425			break;
426		case PST_GROUP:
427			propname = alloc_name_with_prefix("groups", prefix);
428			if (!propname)
429				return -ENOMEM;
430			ret = dev_read_string_index(config, propname, i, &name);
431			free_name_with_prefix(propname, prefix);
432			if (ret)
433				return ret;
434			selector = pinctrl_group_name_to_selector(dev, name);
435			break;
436		case PST_PINMUX: {
437			const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
438			u32 pinmux_group = fdt32_to_cpu(pinmux_groups[i]);
439
440			/* Checked for in pinctrl_generic_get_subnode_type */
441			selector = ops->pinmux_property_set(dev, pinmux_group);
442			break;
443		}
444		case PST_NONE:
445		default:
446			/* skip this node; may contain config child nodes */
447			return 0;
448		}
449
450		if (selector < 0)
451			return selector;
452
453		ret = pinctrl_generic_set_state_one(dev, config, prefix,
454						    subnode_type, selector);
455		if (ret)
456			return ret;
457	}
458
459	return 0;
460}
461
462int pinctrl_generic_set_state_prefix(struct udevice *dev, struct udevice *config,
463				     const char *prefix)
464{
465	struct udevice *child;
466	int ret;
467
468	ret = pinctrl_generic_set_state_subnode(dev, config, prefix);
469	if (ret)
470		return ret;
471
472	for (device_find_first_child(config, &child);
473	     child;
474	     device_find_next_child(&child)) {
475		ret = pinctrl_generic_set_state_subnode(dev, child, prefix);
476		if (ret)
477			return ret;
478	}
479
480	return 0;
481}
482
483int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config)
484{
485	return pinctrl_generic_set_state_prefix(dev, config, NULL);
486}
487