Blame view

drivers/pinctrl/pinmux.c 21.2 KB
af873fcec   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
2744e8afb   Linus Walleij   drivers: create a...
2
3
4
  /*
   * Core driver for the pin muxing portions of the pin control subsystem
   *
e93bcee00   Linus Walleij   pinctrl: move gen...
5
   * Copyright (C) 2011-2012 ST-Ericsson SA
2744e8afb   Linus Walleij   drivers: create a...
6
7
8
9
10
   * Written on behalf of Linaro for ST-Ericsson
   * Based on bits of regulator core, gpio core and clk core
   *
   * Author: Linus Walleij <linus.walleij@linaro.org>
   *
7ecdb16fe   Stephen Warren   pinctrl: refactor...
11
   * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
2744e8afb   Linus Walleij   drivers: create a...
12
13
14
15
16
17
18
19
20
21
22
   */
  #define pr_fmt(fmt) "pinmux core: " fmt
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/device.h>
  #include <linux/slab.h>
  #include <linux/radix-tree.h>
  #include <linux/err.h>
  #include <linux/list.h>
97607d157   Linus Walleij   pinctrl: make a c...
23
  #include <linux/string.h>
2744e8afb   Linus Walleij   drivers: create a...
24
25
26
27
28
  #include <linux/debugfs.h>
  #include <linux/seq_file.h>
  #include <linux/pinctrl/machine.h>
  #include <linux/pinctrl/pinmux.h>
  #include "core.h"
befe5bdfb   Linus Walleij   pinctrl: factor p...
29
  #include "pinmux.h"
2744e8afb   Linus Walleij   drivers: create a...
30

03665e0f2   Stephen Warren   pinctrl: Re-order...
31
32
33
  int pinmux_check_ops(struct pinctrl_dev *pctldev)
  {
  	const struct pinmux_ops *ops = pctldev->desc->pmxops;
a1d31f71e   Dong Aisheng   pinctrl: fix pinm...
34
  	unsigned nfuncs;
03665e0f2   Stephen Warren   pinctrl: Re-order...
35
36
37
  	unsigned selector = 0;
  
  	/* Check that we implement required operations */
a1d31f71e   Dong Aisheng   pinctrl: fix pinm...
38
39
  	if (!ops ||
  	    !ops->get_functions_count ||
03665e0f2   Stephen Warren   pinctrl: Re-order...
40
41
  	    !ops->get_function_name ||
  	    !ops->get_function_groups ||
03e9f0cac   Linus Walleij   pinctrl: clean up...
42
  	    !ops->set_mux) {
ad6e1107b   John Crispin   pinctrl: enhance ...
43
44
  		dev_err(pctldev->dev, "pinmux ops lacks necessary functions
  ");
03665e0f2   Stephen Warren   pinctrl: Re-order...
45
  		return -EINVAL;
ad6e1107b   John Crispin   pinctrl: enhance ...
46
  	}
03665e0f2   Stephen Warren   pinctrl: Re-order...
47
  	/* Check that all functions registered have names */
a1d31f71e   Dong Aisheng   pinctrl: fix pinm...
48
  	nfuncs = ops->get_functions_count(pctldev);
d1e90e9e7   Viresh Kumar   pinctrl: replace ...
49
  	while (selector < nfuncs) {
03665e0f2   Stephen Warren   pinctrl: Re-order...
50
51
52
  		const char *fname = ops->get_function_name(pctldev,
  							   selector);
  		if (!fname) {
a1d31f71e   Dong Aisheng   pinctrl: fix pinm...
53
54
  			dev_err(pctldev->dev, "pinmux ops has no name for function%u
  ",
03665e0f2   Stephen Warren   pinctrl: Re-order...
55
56
57
58
59
60
61
62
  				selector);
  			return -EINVAL;
  		}
  		selector++;
  	}
  
  	return 0;
  }
3f713b7c2   Masahiro Yamada   pinctrl: move con...
63
  int pinmux_validate_map(const struct pinctrl_map *map, int i)
1e2082b52   Stephen Warren   pinctrl: enhance ...
64
65
66
67
68
69
70
71
72
73
  {
  	if (!map->data.mux.function) {
  		pr_err("failed to register map %s (%d): no function given
  ",
  		       map->name, i);
  		return -EINVAL;
  	}
  
  	return 0;
  }
2744e8afb   Linus Walleij   drivers: create a...
74
  /**
472a61e77   Stefan Wahren   pinctrl/gpio: Tak...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
   * pinmux_can_be_used_for_gpio() - check if a specific pin
   *	is either muxed to a different function or used as gpio.
   *
   * @pin: the pin number in the global pin space
   *
   * Controllers not defined as strict will always return true,
   * menaning that the gpio can be used.
   */
  bool pinmux_can_be_used_for_gpio(struct pinctrl_dev *pctldev, unsigned pin)
  {
  	struct pin_desc *desc = pin_desc_get(pctldev, pin);
  	const struct pinmux_ops *ops = pctldev->desc->pmxops;
  
  	/* Can't inspect pin, assume it can be used */
0ef6ac6c1   Alexandre Torgue   pinctrl: pinmux: ...
89
  	if (!desc || !ops)
472a61e77   Stefan Wahren   pinctrl/gpio: Tak...
90
91
92
93
94
95
96
97
98
  		return true;
  
  	if (ops->strict && desc->mux_usecount)
  		return false;
  
  	return !(ops->strict && !!desc->gpio_owner);
  }
  
  /**
2744e8afb   Linus Walleij   drivers: create a...
99
100
   * pin_request() - request a single pin to be muxed in, typically for GPIO
   * @pin: the pin number in the global pin space
3cc70ed32   Stephen Warren   pinctrl: record a...
101
102
   * @owner: a representation of the owner of this pin; typically the device
   *	name that controls its mux function, or the requested GPIO name
2744e8afb   Linus Walleij   drivers: create a...
103
104
105
106
   * @gpio_range: the range matching the GPIO pin if this is a request for a
   *	single GPIO pin
   */
  static int pin_request(struct pinctrl_dev *pctldev,
3cc70ed32   Stephen Warren   pinctrl: record a...
107
  		       int pin, const char *owner,
2744e8afb   Linus Walleij   drivers: create a...
108
109
110
111
112
  		       struct pinctrl_gpio_range *gpio_range)
  {
  	struct pin_desc *desc;
  	const struct pinmux_ops *ops = pctldev->desc->pmxops;
  	int status = -EINVAL;
2744e8afb   Linus Walleij   drivers: create a...
113
114
  	desc = pin_desc_get(pctldev, pin);
  	if (desc == NULL) {
51cd24ee6   Stephen Warren   pinctrl: don't cr...
115
  		dev_err(pctldev->dev,
d4705316c   Stephen Warren   pinctrl: add more...
116
117
118
  			"pin %d is not registered so it cannot be requested
  ",
  			pin);
2744e8afb   Linus Walleij   drivers: create a...
119
120
  		goto out;
  	}
d0bd8df56   Dong Aisheng   pinctrl: show pin...
121
122
123
  	dev_dbg(pctldev->dev, "request pin %d (%s) for %s
  ",
  		pin, desc->name, owner);
b1eb8fabc   Vladimir Zapolskiy   pinctrl: simplify...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  	if ((!gpio_range || ops->strict) &&
  	    desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
  		dev_err(pctldev->dev,
  			"pin %s already requested by %s; cannot claim for %s
  ",
  			desc->name, desc->mux_owner, owner);
  		goto out;
  	}
  
  	if ((gpio_range || ops->strict) && desc->gpio_owner) {
  		dev_err(pctldev->dev,
  			"pin %s already requested by %s; cannot claim for %s
  ",
  			desc->name, desc->gpio_owner, owner);
  		goto out;
  	}
0e3db173e   Stephen Warren   pinctrl: add usec...
140

b1eb8fabc   Vladimir Zapolskiy   pinctrl: simplify...
141
  	if (gpio_range) {
652162d46   Stephen Warren   pinctrl: allow co...
142
143
  		desc->gpio_owner = owner;
  	} else {
652162d46   Stephen Warren   pinctrl: allow co...
144
145
146
147
148
149
  		desc->mux_usecount++;
  		if (desc->mux_usecount > 1)
  			return 0;
  
  		desc->mux_owner = owner;
  	}
2744e8afb   Linus Walleij   drivers: create a...
150
151
152
  
  	/* Let each pin increase references to this module */
  	if (!try_module_get(pctldev->owner)) {
51cd24ee6   Stephen Warren   pinctrl: don't cr...
153
  		dev_err(pctldev->dev,
2744e8afb   Linus Walleij   drivers: create a...
154
155
156
157
158
159
160
161
162
163
164
  			"could not increase module refcount for pin %d
  ",
  			pin);
  		status = -EINVAL;
  		goto out_free_pin;
  	}
  
  	/*
  	 * If there is no kind of request function for the pin we just assume
  	 * we got it by default and proceed.
  	 */
3712a3c48   Stephen Warren   pinctrl: add expl...
165
  	if (gpio_range && ops->gpio_request_enable)
2744e8afb   Linus Walleij   drivers: create a...
166
167
168
169
170
171
  		/* This requests and enables a single GPIO pin */
  		status = ops->gpio_request_enable(pctldev, gpio_range, pin);
  	else if (ops->request)
  		status = ops->request(pctldev, pin);
  	else
  		status = 0;
0e3db173e   Stephen Warren   pinctrl: add usec...
172
  	if (status) {
d4705316c   Stephen Warren   pinctrl: add more...
173
174
  		dev_err(pctldev->dev, "request() failed for pin %d
  ", pin);
0e3db173e   Stephen Warren   pinctrl: add usec...
175
176
  		module_put(pctldev->owner);
  	}
2744e8afb   Linus Walleij   drivers: create a...
177
  out_free_pin:
0e3db173e   Stephen Warren   pinctrl: add usec...
178
  	if (status) {
652162d46   Stephen Warren   pinctrl: allow co...
179
180
181
182
183
184
185
  		if (gpio_range) {
  			desc->gpio_owner = NULL;
  		} else {
  			desc->mux_usecount--;
  			if (!desc->mux_usecount)
  				desc->mux_owner = NULL;
  		}
0e3db173e   Stephen Warren   pinctrl: add usec...
186
  	}
2744e8afb   Linus Walleij   drivers: create a...
187
188
  out:
  	if (status)
51cd24ee6   Stephen Warren   pinctrl: don't cr...
189
190
  		dev_err(pctldev->dev, "pin-%d (%s) status %d
  ",
d4705316c   Stephen Warren   pinctrl: add more...
191
  			pin, owner, status);
2744e8afb   Linus Walleij   drivers: create a...
192
193
194
195
196
197
198
199
  
  	return status;
  }
  
  /**
   * pin_free() - release a single muxed in pin so something else can be muxed
   * @pctldev: pin controller device handling this pin
   * @pin: the pin to free
3712a3c48   Stephen Warren   pinctrl: add expl...
200
201
   * @gpio_range: the range matching the GPIO pin if this is a request for a
   *	single GPIO pin
336cdba09   Linus Walleij   pinctrl: document...
202
   *
3cc70ed32   Stephen Warren   pinctrl: record a...
203
204
   * This function returns a pointer to the previous owner. This is used
   * for callers that dynamically allocate an owner name so it can be freed
336cdba09   Linus Walleij   pinctrl: document...
205
   * once the pin is free. This is done for GPIO request functions.
2744e8afb   Linus Walleij   drivers: create a...
206
   */
3712a3c48   Stephen Warren   pinctrl: add expl...
207
208
  static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
  			    struct pinctrl_gpio_range *gpio_range)
2744e8afb   Linus Walleij   drivers: create a...
209
210
211
  {
  	const struct pinmux_ops *ops = pctldev->desc->pmxops;
  	struct pin_desc *desc;
3cc70ed32   Stephen Warren   pinctrl: record a...
212
  	const char *owner;
2744e8afb   Linus Walleij   drivers: create a...
213
214
215
  
  	desc = pin_desc_get(pctldev, pin);
  	if (desc == NULL) {
51cd24ee6   Stephen Warren   pinctrl: don't cr...
216
  		dev_err(pctldev->dev,
2744e8afb   Linus Walleij   drivers: create a...
217
218
  			"pin is not registered so it cannot be freed
  ");
3712a3c48   Stephen Warren   pinctrl: add expl...
219
  		return NULL;
2744e8afb   Linus Walleij   drivers: create a...
220
  	}
652162d46   Stephen Warren   pinctrl: allow co...
221
  	if (!gpio_range) {
740924a26   Richard Genoud   pinmux: forbid mu...
222
223
224
225
226
  		/*
  		 * A pin should not be freed more times than allocated.
  		 */
  		if (WARN_ON(!desc->mux_usecount))
  			return NULL;
652162d46   Stephen Warren   pinctrl: allow co...
227
228
229
230
  		desc->mux_usecount--;
  		if (desc->mux_usecount)
  			return NULL;
  	}
0e3db173e   Stephen Warren   pinctrl: add usec...
231

3712a3c48   Stephen Warren   pinctrl: add expl...
232
233
234
235
236
237
238
  	/*
  	 * If there is no kind of request function for the pin we just assume
  	 * we got it by default and proceed.
  	 */
  	if (gpio_range && ops->gpio_disable_free)
  		ops->gpio_disable_free(pctldev, gpio_range, pin);
  	else if (ops->free)
2744e8afb   Linus Walleij   drivers: create a...
239
  		ops->free(pctldev, pin);
652162d46   Stephen Warren   pinctrl: allow co...
240
241
242
243
244
245
246
247
  	if (gpio_range) {
  		owner = desc->gpio_owner;
  		desc->gpio_owner = NULL;
  	} else {
  		owner = desc->mux_owner;
  		desc->mux_owner = NULL;
  		desc->mux_setting = NULL;
  	}
2744e8afb   Linus Walleij   drivers: create a...
248
  	module_put(pctldev->owner);
3712a3c48   Stephen Warren   pinctrl: add expl...
249

3cc70ed32   Stephen Warren   pinctrl: record a...
250
  	return owner;
2744e8afb   Linus Walleij   drivers: create a...
251
252
253
  }
  
  /**
befe5bdfb   Linus Walleij   pinctrl: factor p...
254
255
256
257
   * pinmux_request_gpio() - request pinmuxing for a GPIO pin
   * @pctldev: pin controller device affected
   * @pin: the pin to mux in for GPIO
   * @range: the applicable GPIO range
2744e8afb   Linus Walleij   drivers: create a...
258
   */
befe5bdfb   Linus Walleij   pinctrl: factor p...
259
260
261
  int pinmux_request_gpio(struct pinctrl_dev *pctldev,
  			struct pinctrl_gpio_range *range,
  			unsigned pin, unsigned gpio)
2744e8afb   Linus Walleij   drivers: create a...
262
  {
3cc70ed32   Stephen Warren   pinctrl: record a...
263
  	const char *owner;
2744e8afb   Linus Walleij   drivers: create a...
264
  	int ret;
2744e8afb   Linus Walleij   drivers: create a...
265
266
  
  	/* Conjure some name stating what chip and pin this is taken by */
23a895aee   Thomas Petazzoni   pinctrl: use kasp...
267
  	owner = kasprintf(GFP_KERNEL, "%s:%d", range->name, gpio);
3cc70ed32   Stephen Warren   pinctrl: record a...
268
  	if (!owner)
1fb1f0540   Masahiro Yamada   pinctrl: return -...
269
  		return -ENOMEM;
5d2eaf809   Stephen Warren   pinctrl: Don't co...
270

3cc70ed32   Stephen Warren   pinctrl: record a...
271
  	ret = pin_request(pctldev, pin, owner, range);
5d2eaf809   Stephen Warren   pinctrl: Don't co...
272
  	if (ret < 0)
3cc70ed32   Stephen Warren   pinctrl: record a...
273
  		kfree(owner);
5d2eaf809   Stephen Warren   pinctrl: Don't co...
274
275
  
  	return ret;
2744e8afb   Linus Walleij   drivers: create a...
276
  }
2744e8afb   Linus Walleij   drivers: create a...
277
278
  
  /**
befe5bdfb   Linus Walleij   pinctrl: factor p...
279
280
281
282
   * pinmux_free_gpio() - release a pin from GPIO muxing
   * @pctldev: the pin controller device for the pin
   * @pin: the affected currently GPIO-muxed in pin
   * @range: applicable GPIO range
2744e8afb   Linus Walleij   drivers: create a...
283
   */
befe5bdfb   Linus Walleij   pinctrl: factor p...
284
285
  void pinmux_free_gpio(struct pinctrl_dev *pctldev, unsigned pin,
  		      struct pinctrl_gpio_range *range)
2744e8afb   Linus Walleij   drivers: create a...
286
  {
3cc70ed32   Stephen Warren   pinctrl: record a...
287
  	const char *owner;
2744e8afb   Linus Walleij   drivers: create a...
288

3cc70ed32   Stephen Warren   pinctrl: record a...
289
290
  	owner = pin_free(pctldev, pin, range);
  	kfree(owner);
2744e8afb   Linus Walleij   drivers: create a...
291
  }
2744e8afb   Linus Walleij   drivers: create a...
292

befe5bdfb   Linus Walleij   pinctrl: factor p...
293
294
295
296
297
298
299
300
301
302
  /**
   * pinmux_gpio_direction() - set the direction of a single muxed-in GPIO pin
   * @pctldev: the pin controller handling this pin
   * @range: applicable GPIO range
   * @pin: the affected GPIO pin in this controller
   * @input: true if we set the pin as input, false for output
   */
  int pinmux_gpio_direction(struct pinctrl_dev *pctldev,
  			  struct pinctrl_gpio_range *range,
  			  unsigned pin, bool input)
542e704f3   Linus Walleij   pinctrl: GPIO dir...
303
  {
542e704f3   Linus Walleij   pinctrl: GPIO dir...
304
305
  	const struct pinmux_ops *ops;
  	int ret;
542e704f3   Linus Walleij   pinctrl: GPIO dir...
306
307
  
  	ops = pctldev->desc->pmxops;
542e704f3   Linus Walleij   pinctrl: GPIO dir...
308
309
310
311
312
313
314
  	if (ops->gpio_set_direction)
  		ret = ops->gpio_set_direction(pctldev, range, pin, input);
  	else
  		ret = 0;
  
  	return ret;
  }
7ecdb16fe   Stephen Warren   pinctrl: refactor...
315
316
  static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
  					const char *function)
2744e8afb   Linus Walleij   drivers: create a...
317
318
  {
  	const struct pinmux_ops *ops = pctldev->desc->pmxops;
d1e90e9e7   Viresh Kumar   pinctrl: replace ...
319
  	unsigned nfuncs = ops->get_functions_count(pctldev);
2744e8afb   Linus Walleij   drivers: create a...
320
321
322
  	unsigned selector = 0;
  
  	/* See if this pctldev has this function */
d1e90e9e7   Viresh Kumar   pinctrl: replace ...
323
  	while (selector < nfuncs) {
163dc9f39   Masahiro Yamada   pinctrl: join lin...
324
  		const char *fname = ops->get_function_name(pctldev, selector);
2744e8afb   Linus Walleij   drivers: create a...
325

7ecdb16fe   Stephen Warren   pinctrl: refactor...
326
327
  		if (!strcmp(function, fname))
  			return selector;
2744e8afb   Linus Walleij   drivers: create a...
328

2744e8afb   Linus Walleij   drivers: create a...
329
330
  		selector++;
  	}
2744e8afb   Linus Walleij   drivers: create a...
331
332
  	return -EINVAL;
  }
3f713b7c2   Masahiro Yamada   pinctrl: move con...
333
  int pinmux_map_to_setting(const struct pinctrl_map *map,
7ecdb16fe   Stephen Warren   pinctrl: refactor...
334
  			  struct pinctrl_setting *setting)
2744e8afb   Linus Walleij   drivers: create a...
335
  {
7ecdb16fe   Stephen Warren   pinctrl: refactor...
336
337
  	struct pinctrl_dev *pctldev = setting->pctldev;
  	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
7ecdb16fe   Stephen Warren   pinctrl: refactor...
338
339
  	char const * const *groups;
  	unsigned num_groups;
2744e8afb   Linus Walleij   drivers: create a...
340
  	int ret;
7ecdb16fe   Stephen Warren   pinctrl: refactor...
341
  	const char *group;
2744e8afb   Linus Walleij   drivers: create a...
342

ad8bb720c   Dong Aisheng   pinctrl: add some...
343
344
345
346
347
  	if (!pmxops) {
  		dev_err(pctldev->dev, "does not support mux function
  ");
  		return -EINVAL;
  	}
15f70e1b9   John Crispin   pinctrl: fix sign...
348
  	ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
ad6e1107b   John Crispin   pinctrl: enhance ...
349
350
351
352
  	if (ret < 0) {
  		dev_err(pctldev->dev, "invalid function %s in map table
  ",
  			map->data.mux.function);
15f70e1b9   John Crispin   pinctrl: fix sign...
353
  		return ret;
ad6e1107b   John Crispin   pinctrl: enhance ...
354
  	}
15f70e1b9   John Crispin   pinctrl: fix sign...
355
  	setting->data.mux.func = ret;
2744e8afb   Linus Walleij   drivers: create a...
356

1e2082b52   Stephen Warren   pinctrl: enhance ...
357
  	ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
7ecdb16fe   Stephen Warren   pinctrl: refactor...
358
  					  &groups, &num_groups);
ad6e1107b   John Crispin   pinctrl: enhance ...
359
360
361
362
  	if (ret < 0) {
  		dev_err(pctldev->dev, "can't query groups for function %s
  ",
  			map->data.mux.function);
7ecdb16fe   Stephen Warren   pinctrl: refactor...
363
  		return ret;
ad6e1107b   John Crispin   pinctrl: enhance ...
364
365
366
367
368
369
  	}
  	if (!num_groups) {
  		dev_err(pctldev->dev,
  			"function %s can't be selected on any group
  ",
  			map->data.mux.function);
2744e8afb   Linus Walleij   drivers: create a...
370
  		return -EINVAL;
ad6e1107b   John Crispin   pinctrl: enhance ...
371
  	}
1e2082b52   Stephen Warren   pinctrl: enhance ...
372
  	if (map->data.mux.group) {
1e2082b52   Stephen Warren   pinctrl: enhance ...
373
  		group = map->data.mux.group;
dff435944   Andy Shevchenko   pinctrl: convert ...
374
375
  		ret = match_string(groups, num_groups, group);
  		if (ret < 0) {
ad6e1107b   John Crispin   pinctrl: enhance ...
376
377
378
379
  			dev_err(pctldev->dev,
  				"invalid group \"%s\" for function \"%s\"
  ",
  				group, map->data.mux.function);
dff435944   Andy Shevchenko   pinctrl: convert ...
380
  			return ret;
ad6e1107b   John Crispin   pinctrl: enhance ...
381
  		}
7ecdb16fe   Stephen Warren   pinctrl: refactor...
382
383
  	} else {
  		group = groups[0];
2744e8afb   Linus Walleij   drivers: create a...
384
  	}
2744e8afb   Linus Walleij   drivers: create a...
385

15f70e1b9   John Crispin   pinctrl: fix sign...
386
  	ret = pinctrl_get_group_selector(pctldev, group);
ad6e1107b   John Crispin   pinctrl: enhance ...
387
388
389
390
  	if (ret < 0) {
  		dev_err(pctldev->dev, "invalid group %s in map table
  ",
  			map->data.mux.group);
15f70e1b9   John Crispin   pinctrl: fix sign...
391
  		return ret;
ad6e1107b   John Crispin   pinctrl: enhance ...
392
  	}
15f70e1b9   John Crispin   pinctrl: fix sign...
393
  	setting->data.mux.group = ret;
2744e8afb   Linus Walleij   drivers: create a...
394

2744e8afb   Linus Walleij   drivers: create a...
395
396
  	return 0;
  }
3f713b7c2   Masahiro Yamada   pinctrl: move con...
397
  void pinmux_free_setting(const struct pinctrl_setting *setting)
2744e8afb   Linus Walleij   drivers: create a...
398
  {
1a78958dc   Linus Walleij   pinctrl: reserve ...
399
  	/* This function is currently unused */
2744e8afb   Linus Walleij   drivers: create a...
400
  }
2744e8afb   Linus Walleij   drivers: create a...
401

3f713b7c2   Masahiro Yamada   pinctrl: move con...
402
  int pinmux_enable_setting(const struct pinctrl_setting *setting)
2744e8afb   Linus Walleij   drivers: create a...
403
  {
7ecdb16fe   Stephen Warren   pinctrl: refactor...
404
  	struct pinctrl_dev *pctldev = setting->pctldev;
ba110d90c   Stephen Warren   pinctrl: Show sel...
405
  	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
befe5bdfb   Linus Walleij   pinctrl: factor p...
406
  	const struct pinmux_ops *ops = pctldev->desc->pmxops;
e5b3b2d9e   Antoine Ténart   pinctrl: allows n...
407
408
409
  	int ret = 0;
  	const unsigned *pins = NULL;
  	unsigned num_pins = 0;
ba110d90c   Stephen Warren   pinctrl: Show sel...
410
411
  	int i;
  	struct pin_desc *desc;
e5b3b2d9e   Antoine Ténart   pinctrl: allows n...
412
413
414
  	if (pctlops->get_group_pins)
  		ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
  					      &pins, &num_pins);
ba110d90c   Stephen Warren   pinctrl: Show sel...
415
  	if (ret) {
1c8e79443   Linus Walleij   pinctrl: improve ...
416
  		const char *gname;
ba110d90c   Stephen Warren   pinctrl: Show sel...
417
  		/* errors only affect debug data, so just warn */
1c8e79443   Linus Walleij   pinctrl: improve ...
418
419
  		gname = pctlops->get_group_name(pctldev,
  						setting->data.mux.group);
ba110d90c   Stephen Warren   pinctrl: Show sel...
420
  		dev_warn(pctldev->dev,
1c8e79443   Linus Walleij   pinctrl: improve ...
421
422
423
  			 "could not get pins for group %s
  ",
  			 gname);
ba110d90c   Stephen Warren   pinctrl: Show sel...
424
425
  		num_pins = 0;
  	}
1a78958dc   Linus Walleij   pinctrl: reserve ...
426
427
428
429
  	/* Try to allocate all pins in this group, one by one */
  	for (i = 0; i < num_pins; i++) {
  		ret = pin_request(pctldev, pins[i], setting->dev_name, NULL);
  		if (ret) {
1c8e79443   Linus Walleij   pinctrl: improve ...
430
431
432
433
434
435
436
  			const char *gname;
  			const char *pname;
  
  			desc = pin_desc_get(pctldev, pins[i]);
  			pname = desc ? desc->name : "non-existing";
  			gname = pctlops->get_group_name(pctldev,
  						setting->data.mux.group);
1a78958dc   Linus Walleij   pinctrl: reserve ...
437
  			dev_err(pctldev->dev,
1c8e79443   Linus Walleij   pinctrl: improve ...
438
439
440
441
442
  				"could not request pin %d (%s) from group %s "
  				" on device %s
  ",
  				pins[i], pname, gname,
  				pinctrl_dev_get_name(pctldev));
e38d457de   Axel Lin   pinctrl: pinmux: ...
443
  			goto err_pin_request;
1a78958dc   Linus Walleij   pinctrl: reserve ...
444
445
446
447
  		}
  	}
  
  	/* Now that we have acquired the pins, encode the mux setting */
ba110d90c   Stephen Warren   pinctrl: Show sel...
448
449
450
451
452
453
454
455
456
457
458
  	for (i = 0; i < num_pins; i++) {
  		desc = pin_desc_get(pctldev, pins[i]);
  		if (desc == NULL) {
  			dev_warn(pctldev->dev,
  				 "could not get pin desc for pin %d
  ",
  				 pins[i]);
  			continue;
  		}
  		desc->mux_setting = &(setting->data.mux);
  	}
2744e8afb   Linus Walleij   drivers: create a...
459

03e9f0cac   Linus Walleij   pinctrl: clean up...
460
461
  	ret = ops->set_mux(pctldev, setting->data.mux.func,
  			   setting->data.mux.group);
e38d457de   Axel Lin   pinctrl: pinmux: ...
462
463
  
  	if (ret)
03e9f0cac   Linus Walleij   pinctrl: clean up...
464
  		goto err_set_mux;
e38d457de   Axel Lin   pinctrl: pinmux: ...
465
466
  
  	return 0;
03e9f0cac   Linus Walleij   pinctrl: clean up...
467
  err_set_mux:
e38d457de   Axel Lin   pinctrl: pinmux: ...
468
469
470
471
472
473
474
475
476
477
478
  	for (i = 0; i < num_pins; i++) {
  		desc = pin_desc_get(pctldev, pins[i]);
  		if (desc)
  			desc->mux_setting = NULL;
  	}
  err_pin_request:
  	/* On error release all taken pins */
  	while (--i >= 0)
  		pin_free(pctldev, pins[i], NULL);
  
  	return ret;
2744e8afb   Linus Walleij   drivers: create a...
479
  }
2744e8afb   Linus Walleij   drivers: create a...
480

3f713b7c2   Masahiro Yamada   pinctrl: move con...
481
  void pinmux_disable_setting(const struct pinctrl_setting *setting)
2744e8afb   Linus Walleij   drivers: create a...
482
  {
7ecdb16fe   Stephen Warren   pinctrl: refactor...
483
  	struct pinctrl_dev *pctldev = setting->pctldev;
ba110d90c   Stephen Warren   pinctrl: Show sel...
484
  	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
e5b3b2d9e   Antoine Ténart   pinctrl: allows n...
485
486
487
  	int ret = 0;
  	const unsigned *pins = NULL;
  	unsigned num_pins = 0;
ba110d90c   Stephen Warren   pinctrl: Show sel...
488
489
  	int i;
  	struct pin_desc *desc;
e5b3b2d9e   Antoine Ténart   pinctrl: allows n...
490
491
492
  	if (pctlops->get_group_pins)
  		ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
  					      &pins, &num_pins);
ba110d90c   Stephen Warren   pinctrl: Show sel...
493
  	if (ret) {
1c8e79443   Linus Walleij   pinctrl: improve ...
494
  		const char *gname;
ba110d90c   Stephen Warren   pinctrl: Show sel...
495
  		/* errors only affect debug data, so just warn */
1c8e79443   Linus Walleij   pinctrl: improve ...
496
497
  		gname = pctlops->get_group_name(pctldev,
  						setting->data.mux.group);
ba110d90c   Stephen Warren   pinctrl: Show sel...
498
  		dev_warn(pctldev->dev,
1c8e79443   Linus Walleij   pinctrl: improve ...
499
500
501
  			 "could not get pins for group %s
  ",
  			 gname);
ba110d90c   Stephen Warren   pinctrl: Show sel...
502
503
  		num_pins = 0;
  	}
1a78958dc   Linus Walleij   pinctrl: reserve ...
504
  	/* Flag the descs that no setting is active */
ba110d90c   Stephen Warren   pinctrl: Show sel...
505
506
507
508
509
510
511
512
513
  	for (i = 0; i < num_pins; i++) {
  		desc = pin_desc_get(pctldev, pins[i]);
  		if (desc == NULL) {
  			dev_warn(pctldev->dev,
  				 "could not get pin desc for pin %d
  ",
  				 pins[i]);
  			continue;
  		}
744f0a9ad   Sonic Zhang   pinctrl: pinmux: ...
514
  		if (desc->mux_setting == &(setting->data.mux)) {
744f0a9ad   Sonic Zhang   pinctrl: pinmux: ...
515
  			pin_free(pctldev, pins[i], NULL);
1c8e79443   Linus Walleij   pinctrl: improve ...
516
517
  		} else {
  			const char *gname;
1c8e79443   Linus Walleij   pinctrl: improve ...
518

1c8e79443   Linus Walleij   pinctrl: improve ...
519
520
521
522
523
524
  			gname = pctlops->get_group_name(pctldev,
  						setting->data.mux.group);
  			dev_warn(pctldev->dev,
  				 "not freeing pin %d (%s) as part of "
  				 "deactivating group %s - it is already "
  				 "used for some other setting",
808e657c5   Michael Opdenacker   pinctrl: remove m...
525
  				 pins[i], desc->name, gname);
744f0a9ad   Sonic Zhang   pinctrl: pinmux: ...
526
  		}
ba110d90c   Stephen Warren   pinctrl: Show sel...
527
  	}
2744e8afb   Linus Walleij   drivers: create a...
528
  }
2744e8afb   Linus Walleij   drivers: create a...
529

2744e8afb   Linus Walleij   drivers: create a...
530
531
532
533
534
535
536
  #ifdef CONFIG_DEBUG_FS
  
  /* Called from pincontrol core */
  static int pinmux_functions_show(struct seq_file *s, void *what)
  {
  	struct pinctrl_dev *pctldev = s->private;
  	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
ad8bb720c   Dong Aisheng   pinctrl: add some...
537
  	unsigned nfuncs;
2744e8afb   Linus Walleij   drivers: create a...
538
  	unsigned func_selector = 0;
ad8bb720c   Dong Aisheng   pinctrl: add some...
539
540
  	if (!pmxops)
  		return 0;
57b676f9c   Stephen Warren   pinctrl: fix and ...
541

42fed7ba4   Patrice Chotard   pinctrl: move sub...
542
  	mutex_lock(&pctldev->mutex);
ad8bb720c   Dong Aisheng   pinctrl: add some...
543
  	nfuncs = pmxops->get_functions_count(pctldev);
d1e90e9e7   Viresh Kumar   pinctrl: replace ...
544
  	while (func_selector < nfuncs) {
2744e8afb   Linus Walleij   drivers: create a...
545
546
547
548
549
550
551
552
553
  		const char *func = pmxops->get_function_name(pctldev,
  							  func_selector);
  		const char * const *groups;
  		unsigned num_groups;
  		int ret;
  		int i;
  
  		ret = pmxops->get_function_groups(pctldev, func_selector,
  						  &groups, &num_groups);
9d7ebbbf2   Ludovic Desroches   pinctrl: don't pr...
554
  		if (ret) {
2744e8afb   Linus Walleij   drivers: create a...
555
556
557
  			seq_printf(s, "function %s: COULD NOT GET GROUPS
  ",
  				   func);
9d7ebbbf2   Ludovic Desroches   pinctrl: don't pr...
558
559
560
  			func_selector++;
  			continue;
  		}
2744e8afb   Linus Walleij   drivers: create a...
561
562
563
564
565
566
567
568
  
  		seq_printf(s, "function: %s, groups = [ ", func);
  		for (i = 0; i < num_groups; i++)
  			seq_printf(s, "%s ", groups[i]);
  		seq_puts(s, "]
  ");
  
  		func_selector++;
2744e8afb   Linus Walleij   drivers: create a...
569
  	}
42fed7ba4   Patrice Chotard   pinctrl: move sub...
570
  	mutex_unlock(&pctldev->mutex);
57b676f9c   Stephen Warren   pinctrl: fix and ...
571

2744e8afb   Linus Walleij   drivers: create a...
572
573
574
575
576
577
  	return 0;
  }
  
  static int pinmux_pins_show(struct seq_file *s, void *what)
  {
  	struct pinctrl_dev *pctldev = s->private;
ba110d90c   Stephen Warren   pinctrl: Show sel...
578
579
  	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
  	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
706e8520e   Chanho Park   pinctrl: correct ...
580
  	unsigned i, pin;
2744e8afb   Linus Walleij   drivers: create a...
581

ad8bb720c   Dong Aisheng   pinctrl: add some...
582
583
  	if (!pmxops)
  		return 0;
2744e8afb   Linus Walleij   drivers: create a...
584
585
  	seq_puts(s, "Pinmux settings per pin
  ");
815088550   Linus Walleij   pinctrl: improve ...
586
587
588
589
590
591
592
593
  	if (pmxops->strict)
  		seq_puts(s,
  		 "Format: pin (name): mux_owner|gpio_owner (strict) hog?
  ");
  	else
  		seq_puts(s,
  		"Format: pin (name): mux_owner gpio_owner hog?
  ");
2744e8afb   Linus Walleij   drivers: create a...
594

42fed7ba4   Patrice Chotard   pinctrl: move sub...
595
  	mutex_lock(&pctldev->mutex);
57b676f9c   Stephen Warren   pinctrl: fix and ...
596

706e8520e   Chanho Park   pinctrl: correct ...
597
598
  	/* The pin number can be retrived from the pin controller descriptor */
  	for (i = 0; i < pctldev->desc->npins; i++) {
2744e8afb   Linus Walleij   drivers: create a...
599
  		struct pin_desc *desc;
1cf94c45c   Linus Walleij   pinctrl: make the...
600
  		bool is_hog = false;
2744e8afb   Linus Walleij   drivers: create a...
601

706e8520e   Chanho Park   pinctrl: correct ...
602
  		pin = pctldev->desc->pins[i].number;
2744e8afb   Linus Walleij   drivers: create a...
603
  		desc = pin_desc_get(pctldev, pin);
706e8520e   Chanho Park   pinctrl: correct ...
604
  		/* Skip if we cannot search the pin */
2744e8afb   Linus Walleij   drivers: create a...
605
606
  		if (desc == NULL)
  			continue;
652162d46   Stephen Warren   pinctrl: allow co...
607
608
  		if (desc->mux_owner &&
  		    !strcmp(desc->mux_owner, pinctrl_dev_get_name(pctldev)))
1cf94c45c   Linus Walleij   pinctrl: make the...
609
  			is_hog = true;
815088550   Linus Walleij   pinctrl: improve ...
610
611
612
  		if (pmxops->strict) {
  			if (desc->mux_owner)
  				seq_printf(s, "pin %d (%s): device %s%s",
cf9d994dc   Masahiro Yamada   pinctrl: do not c...
613
  					   pin, desc->name, desc->mux_owner,
815088550   Linus Walleij   pinctrl: improve ...
614
615
616
  					   is_hog ? " (HOG)" : "");
  			else if (desc->gpio_owner)
  				seq_printf(s, "pin %d (%s): GPIO %s",
cf9d994dc   Masahiro Yamada   pinctrl: do not c...
617
  					   pin, desc->name, desc->gpio_owner);
815088550   Linus Walleij   pinctrl: improve ...
618
619
  			else
  				seq_printf(s, "pin %d (%s): UNCLAIMED",
cf9d994dc   Masahiro Yamada   pinctrl: do not c...
620
  					   pin, desc->name);
815088550   Linus Walleij   pinctrl: improve ...
621
622
  		} else {
  			/* For non-strict controllers */
cf9d994dc   Masahiro Yamada   pinctrl: do not c...
623
  			seq_printf(s, "pin %d (%s): %s %s%s", pin, desc->name,
815088550   Linus Walleij   pinctrl: improve ...
624
625
626
627
628
629
  				   desc->mux_owner ? desc->mux_owner
  				   : "(MUX UNCLAIMED)",
  				   desc->gpio_owner ? desc->gpio_owner
  				   : "(GPIO UNCLAIMED)",
  				   is_hog ? " (HOG)" : "");
  		}
ba110d90c   Stephen Warren   pinctrl: Show sel...
630

815088550   Linus Walleij   pinctrl: improve ...
631
  		/* If mux: print function+group claiming the pin */
ba110d90c   Stephen Warren   pinctrl: Show sel...
632
633
634
635
636
637
638
639
  		if (desc->mux_setting)
  			seq_printf(s, " function %s group %s
  ",
  				   pmxops->get_function_name(pctldev,
  					desc->mux_setting->func),
  				   pctlops->get_group_name(pctldev,
  					desc->mux_setting->group));
  		else
ffd10c2ec   Markus Elfring   pinctrl: pinmux: ...
640
641
  			seq_putc(s, '
  ');
2744e8afb   Linus Walleij   drivers: create a...
642
  	}
42fed7ba4   Patrice Chotard   pinctrl: move sub...
643
  	mutex_unlock(&pctldev->mutex);
57b676f9c   Stephen Warren   pinctrl: fix and ...
644

2744e8afb   Linus Walleij   drivers: create a...
645
646
  	return 0;
  }
3f713b7c2   Masahiro Yamada   pinctrl: move con...
647
  void pinmux_show_map(struct seq_file *s, const struct pinctrl_map *map)
1e2082b52   Stephen Warren   pinctrl: enhance ...
648
649
650
651
652
653
654
655
656
  {
  	seq_printf(s, "group %s
  function %s
  ",
  		map->data.mux.group ? map->data.mux.group : "(default)",
  		map->data.mux.function);
  }
  
  void pinmux_show_setting(struct seq_file *s,
3f713b7c2   Masahiro Yamada   pinctrl: move con...
657
  			 const struct pinctrl_setting *setting)
2744e8afb   Linus Walleij   drivers: create a...
658
  {
7ecdb16fe   Stephen Warren   pinctrl: refactor...
659
660
661
  	struct pinctrl_dev *pctldev = setting->pctldev;
  	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
  	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
1e2082b52   Stephen Warren   pinctrl: enhance ...
662
663
664
665
666
667
  	seq_printf(s, "group: %s (%u) function: %s (%u)
  ",
  		   pctlops->get_group_name(pctldev, setting->data.mux.group),
  		   setting->data.mux.group,
  		   pmxops->get_function_name(pctldev, setting->data.mux.func),
  		   setting->data.mux.func);
2744e8afb   Linus Walleij   drivers: create a...
668
  }
0819dc72e   Yangtao Li   pinctrl: Change t...
669
670
  DEFINE_SHOW_ATTRIBUTE(pinmux_functions);
  DEFINE_SHOW_ATTRIBUTE(pinmux_pins);
2744e8afb   Linus Walleij   drivers: create a...
671

2744e8afb   Linus Walleij   drivers: create a...
672
673
674
675
  void pinmux_init_device_debugfs(struct dentry *devroot,
  			 struct pinctrl_dev *pctldev)
  {
  	debugfs_create_file("pinmux-functions", S_IFREG | S_IRUGO,
0819dc72e   Yangtao Li   pinctrl: Change t...
676
  			    devroot, pctldev, &pinmux_functions_fops);
2744e8afb   Linus Walleij   drivers: create a...
677
  	debugfs_create_file("pinmux-pins", S_IFREG | S_IRUGO,
0819dc72e   Yangtao Li   pinctrl: Change t...
678
  			    devroot, pctldev, &pinmux_pins_fops);
2744e8afb   Linus Walleij   drivers: create a...
679
680
681
  }
  
  #endif /* CONFIG_DEBUG_FS */
a76edc89b   Tony Lindgren   pinctrl: core: Ad...
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
  
  #ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS
  
  /**
   * pinmux_generic_get_function_count() - returns number of functions
   * @pctldev: pin controller device
   */
  int pinmux_generic_get_function_count(struct pinctrl_dev *pctldev)
  {
  	return pctldev->num_functions;
  }
  EXPORT_SYMBOL_GPL(pinmux_generic_get_function_count);
  
  /**
   * pinmux_generic_get_function_name() - returns the function name
   * @pctldev: pin controller device
   * @selector: function number
   */
  const char *
  pinmux_generic_get_function_name(struct pinctrl_dev *pctldev,
  				 unsigned int selector)
  {
  	struct function_desc *function;
  
  	function = radix_tree_lookup(&pctldev->pin_function_tree,
  				     selector);
  	if (!function)
  		return NULL;
  
  	return function->name;
  }
  EXPORT_SYMBOL_GPL(pinmux_generic_get_function_name);
  
  /**
   * pinmux_generic_get_function_groups() - gets the function groups
   * @pctldev: pin controller device
   * @selector: function number
   * @groups: array of pin groups
   * @num_groups: number of pin groups
   */
  int pinmux_generic_get_function_groups(struct pinctrl_dev *pctldev,
  				       unsigned int selector,
  				       const char * const **groups,
  				       unsigned * const num_groups)
  {
  	struct function_desc *function;
  
  	function = radix_tree_lookup(&pctldev->pin_function_tree,
  				     selector);
  	if (!function) {
  		dev_err(pctldev->dev, "%s could not find function%i
  ",
  			__func__, selector);
  		return -EINVAL;
  	}
  	*groups = function->group_names;
  	*num_groups = function->num_group_names;
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(pinmux_generic_get_function_groups);
  
  /**
   * pinmux_generic_get_function() - returns a function based on the number
   * @pctldev: pin controller device
   * @group_selector: function number
   */
  struct function_desc *pinmux_generic_get_function(struct pinctrl_dev *pctldev,
  						  unsigned int selector)
  {
  	struct function_desc *function;
  
  	function = radix_tree_lookup(&pctldev->pin_function_tree,
  				     selector);
  	if (!function)
  		return NULL;
  
  	return function;
  }
  EXPORT_SYMBOL_GPL(pinmux_generic_get_function);
  
  /**
6bffa7e16   Geert Uytterhoeven   pinctrl: pinmux: ...
764
   * pinmux_generic_add_function() - adds a function group
a76edc89b   Tony Lindgren   pinctrl: core: Ad...
765
766
767
768
769
770
771
772
773
774
775
776
777
   * @pctldev: pin controller device
   * @name: name of the function
   * @groups: array of pin groups
   * @num_groups: number of pin groups
   * @data: pin controller driver specific data
   */
  int pinmux_generic_add_function(struct pinctrl_dev *pctldev,
  				const char *name,
  				const char **groups,
  				const unsigned int num_groups,
  				void *data)
  {
  	struct function_desc *function;
f913cfce4   Tony Lindgren   pinctrl: pinmux: ...
778
779
780
781
782
783
784
785
786
787
  	int selector;
  
  	if (!name)
  		return -EINVAL;
  
  	selector = pinmux_func_name_to_selector(pctldev, name);
  	if (selector >= 0)
  		return selector;
  
  	selector = pctldev->num_functions;
a76edc89b   Tony Lindgren   pinctrl: core: Ad...
788
789
790
791
792
793
794
795
796
  
  	function = devm_kzalloc(pctldev->dev, sizeof(*function), GFP_KERNEL);
  	if (!function)
  		return -ENOMEM;
  
  	function->name = name;
  	function->group_names = groups;
  	function->num_group_names = num_groups;
  	function->data = data;
f913cfce4   Tony Lindgren   pinctrl: pinmux: ...
797
  	radix_tree_insert(&pctldev->pin_function_tree, selector, function);
a76edc89b   Tony Lindgren   pinctrl: core: Ad...
798
799
  
  	pctldev->num_functions++;
f913cfce4   Tony Lindgren   pinctrl: pinmux: ...
800
  	return selector;
a76edc89b   Tony Lindgren   pinctrl: core: Ad...
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
  }
  EXPORT_SYMBOL_GPL(pinmux_generic_add_function);
  
  /**
   * pinmux_generic_remove_function() - removes a numbered function
   * @pctldev: pin controller device
   * @selector: function number
   *
   * Note that the caller must take care of locking.
   */
  int pinmux_generic_remove_function(struct pinctrl_dev *pctldev,
  				   unsigned int selector)
  {
  	struct function_desc *function;
  
  	function = radix_tree_lookup(&pctldev->pin_function_tree,
  				     selector);
  	if (!function)
  		return -ENOENT;
  
  	radix_tree_delete(&pctldev->pin_function_tree, selector);
  	devm_kfree(pctldev->dev, function);
  
  	pctldev->num_functions--;
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(pinmux_generic_remove_function);
  
  /**
   * pinmux_generic_free_functions() - removes all functions
   * @pctldev: pin controller device
   *
664b7c472   Tony Lindgren   pinctrl: core: Fi...
834
835
836
   * Note that the caller must take care of locking. The pinctrl
   * functions are allocated with devm_kzalloc() so no need to free
   * them here.
a76edc89b   Tony Lindgren   pinctrl: core: Ad...
837
838
839
840
   */
  void pinmux_generic_free_functions(struct pinctrl_dev *pctldev)
  {
  	struct radix_tree_iter iter;
906a2a395   Masahiro Yamada   pinctrl: add __rc...
841
  	void __rcu **slot;
a76edc89b   Tony Lindgren   pinctrl: core: Ad...
842
843
  
  	radix_tree_for_each_slot(slot, &pctldev->pin_function_tree, &iter, 0)
664b7c472   Tony Lindgren   pinctrl: core: Fi...
844
  		radix_tree_delete(&pctldev->pin_function_tree, iter.index);
a76edc89b   Tony Lindgren   pinctrl: core: Ad...
845
846
847
848
849
  
  	pctldev->num_functions = 0;
  }
  
  #endif /* CONFIG_GENERIC_PINMUX_FUNCTIONS */