xref: /openbmc/linux/drivers/pinctrl/pinmux.c (revision 278002edb19bce2c628fafb0af936e77000f3a5b)
1af873fceSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22744e8afSLinus Walleij /*
32744e8afSLinus Walleij  * Core driver for the pin muxing portions of the pin control subsystem
42744e8afSLinus Walleij  *
5e93bcee0SLinus Walleij  * Copyright (C) 2011-2012 ST-Ericsson SA
62744e8afSLinus Walleij  * Written on behalf of Linaro for ST-Ericsson
72744e8afSLinus Walleij  * Based on bits of regulator core, gpio core and clk core
82744e8afSLinus Walleij  *
92744e8afSLinus Walleij  * Author: Linus Walleij <linus.walleij@linaro.org>
102744e8afSLinus Walleij  *
117ecdb16fSStephen Warren  * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
122744e8afSLinus Walleij  */
132744e8afSLinus Walleij #define pr_fmt(fmt) "pinmux core: " fmt
142744e8afSLinus Walleij 
156199f6beSDrew Fustini #include <linux/ctype.h>
16*2da32aedSMukesh Ojha #include <linux/cleanup.h>
172744e8afSLinus Walleij #include <linux/debugfs.h>
18e5530adcSAndy Shevchenko #include <linux/device.h>
19e5530adcSAndy Shevchenko #include <linux/err.h>
20e5530adcSAndy Shevchenko #include <linux/init.h>
21e5530adcSAndy Shevchenko #include <linux/kernel.h>
22e5530adcSAndy Shevchenko #include <linux/list.h>
23e5530adcSAndy Shevchenko #include <linux/module.h>
24e5530adcSAndy Shevchenko #include <linux/radix-tree.h>
252744e8afSLinus Walleij #include <linux/seq_file.h>
26e5530adcSAndy Shevchenko #include <linux/slab.h>
27e5530adcSAndy Shevchenko #include <linux/string.h>
28e5530adcSAndy Shevchenko 
292744e8afSLinus Walleij #include <linux/pinctrl/machine.h>
30e5530adcSAndy Shevchenko #include <linux/pinctrl/pinctrl.h>
312744e8afSLinus Walleij #include <linux/pinctrl/pinmux.h>
32e5530adcSAndy Shevchenko 
332744e8afSLinus Walleij #include "core.h"
34befe5bdfSLinus Walleij #include "pinmux.h"
352744e8afSLinus Walleij 
pinmux_check_ops(struct pinctrl_dev * pctldev)3603665e0fSStephen Warren int pinmux_check_ops(struct pinctrl_dev *pctldev)
3703665e0fSStephen Warren {
3803665e0fSStephen Warren 	const struct pinmux_ops *ops = pctldev->desc->pmxops;
39a1d31f71SDong Aisheng 	unsigned nfuncs;
4003665e0fSStephen Warren 	unsigned selector = 0;
4103665e0fSStephen Warren 
4203665e0fSStephen Warren 	/* Check that we implement required operations */
43a1d31f71SDong Aisheng 	if (!ops ||
44a1d31f71SDong Aisheng 	    !ops->get_functions_count ||
4503665e0fSStephen Warren 	    !ops->get_function_name ||
4603665e0fSStephen Warren 	    !ops->get_function_groups ||
4703e9f0caSLinus Walleij 	    !ops->set_mux) {
48ad6e1107SJohn Crispin 		dev_err(pctldev->dev, "pinmux ops lacks necessary functions\n");
4903665e0fSStephen Warren 		return -EINVAL;
50ad6e1107SJohn Crispin 	}
5103665e0fSStephen Warren 	/* Check that all functions registered have names */
52a1d31f71SDong Aisheng 	nfuncs = ops->get_functions_count(pctldev);
53d1e90e9eSViresh Kumar 	while (selector < nfuncs) {
5403665e0fSStephen Warren 		const char *fname = ops->get_function_name(pctldev,
5503665e0fSStephen Warren 							   selector);
5603665e0fSStephen Warren 		if (!fname) {
57a1d31f71SDong Aisheng 			dev_err(pctldev->dev, "pinmux ops has no name for function%u\n",
5803665e0fSStephen Warren 				selector);
5903665e0fSStephen Warren 			return -EINVAL;
6003665e0fSStephen Warren 		}
6103665e0fSStephen Warren 		selector++;
6203665e0fSStephen Warren 	}
6303665e0fSStephen Warren 
6403665e0fSStephen Warren 	return 0;
6503665e0fSStephen Warren }
6603665e0fSStephen Warren 
pinmux_validate_map(const struct pinctrl_map * map,int i)673f713b7cSMasahiro Yamada int pinmux_validate_map(const struct pinctrl_map *map, int i)
681e2082b5SStephen Warren {
691e2082b5SStephen Warren 	if (!map->data.mux.function) {
701e2082b5SStephen Warren 		pr_err("failed to register map %s (%d): no function given\n",
711e2082b5SStephen Warren 		       map->name, i);
721e2082b5SStephen Warren 		return -EINVAL;
731e2082b5SStephen Warren 	}
741e2082b5SStephen Warren 
751e2082b5SStephen Warren 	return 0;
761e2082b5SStephen Warren }
771e2082b5SStephen Warren 
782744e8afSLinus Walleij /**
79472a61e7SStefan Wahren  * pinmux_can_be_used_for_gpio() - check if a specific pin
80472a61e7SStefan Wahren  *	is either muxed to a different function or used as gpio.
81472a61e7SStefan Wahren  *
82d340351fSLee Jones  * @pctldev: the associated pin controller device
83472a61e7SStefan Wahren  * @pin: the pin number in the global pin space
84472a61e7SStefan Wahren  *
85472a61e7SStefan Wahren  * Controllers not defined as strict will always return true,
86472a61e7SStefan Wahren  * menaning that the gpio can be used.
87472a61e7SStefan Wahren  */
pinmux_can_be_used_for_gpio(struct pinctrl_dev * pctldev,unsigned pin)88472a61e7SStefan Wahren bool pinmux_can_be_used_for_gpio(struct pinctrl_dev *pctldev, unsigned pin)
89472a61e7SStefan Wahren {
90472a61e7SStefan Wahren 	struct pin_desc *desc = pin_desc_get(pctldev, pin);
91472a61e7SStefan Wahren 	const struct pinmux_ops *ops = pctldev->desc->pmxops;
92472a61e7SStefan Wahren 
93472a61e7SStefan Wahren 	/* Can't inspect pin, assume it can be used */
946ba2fd39SAlexandre Torgue 	if (!desc || !ops)
95472a61e7SStefan Wahren 		return true;
96472a61e7SStefan Wahren 
97*2da32aedSMukesh Ojha 	guard(mutex)(&desc->mux_lock);
98472a61e7SStefan Wahren 	if (ops->strict && desc->mux_usecount)
99472a61e7SStefan Wahren 		return false;
100472a61e7SStefan Wahren 
101472a61e7SStefan Wahren 	return !(ops->strict && !!desc->gpio_owner);
102472a61e7SStefan Wahren }
103472a61e7SStefan Wahren 
104472a61e7SStefan Wahren /**
1052744e8afSLinus Walleij  * pin_request() - request a single pin to be muxed in, typically for GPIO
106d340351fSLee Jones  * @pctldev: the associated pin controller device
1072744e8afSLinus Walleij  * @pin: the pin number in the global pin space
1083cc70ed3SStephen Warren  * @owner: a representation of the owner of this pin; typically the device
1093cc70ed3SStephen Warren  *	name that controls its mux function, or the requested GPIO name
1102744e8afSLinus Walleij  * @gpio_range: the range matching the GPIO pin if this is a request for a
1112744e8afSLinus Walleij  *	single GPIO pin
1122744e8afSLinus Walleij  */
pin_request(struct pinctrl_dev * pctldev,int pin,const char * owner,struct pinctrl_gpio_range * gpio_range)1132744e8afSLinus Walleij static int pin_request(struct pinctrl_dev *pctldev,
1143cc70ed3SStephen Warren 		       int pin, const char *owner,
1152744e8afSLinus Walleij 		       struct pinctrl_gpio_range *gpio_range)
1162744e8afSLinus Walleij {
1172744e8afSLinus Walleij 	struct pin_desc *desc;
1182744e8afSLinus Walleij 	const struct pinmux_ops *ops = pctldev->desc->pmxops;
1192744e8afSLinus Walleij 	int status = -EINVAL;
1202744e8afSLinus Walleij 
1212744e8afSLinus Walleij 	desc = pin_desc_get(pctldev, pin);
1222744e8afSLinus Walleij 	if (desc == NULL) {
12351cd24eeSStephen Warren 		dev_err(pctldev->dev,
124d4705316SStephen Warren 			"pin %d is not registered so it cannot be requested\n",
125d4705316SStephen Warren 			pin);
1262744e8afSLinus Walleij 		goto out;
1272744e8afSLinus Walleij 	}
1282744e8afSLinus Walleij 
129d0bd8df5SDong Aisheng 	dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
130d0bd8df5SDong Aisheng 		pin, desc->name, owner);
131d0bd8df5SDong Aisheng 
132*2da32aedSMukesh Ojha 	scoped_guard(mutex, &desc->mux_lock) {
133b1eb8fabSVladimir Zapolskiy 		if ((!gpio_range || ops->strict) &&
134b1eb8fabSVladimir Zapolskiy 		    desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
135fa76a3dbSSonic Zhang 			dev_err(pctldev->dev,
136fa76a3dbSSonic Zhang 				"pin %s already requested by %s; cannot claim for %s\n",
137fa76a3dbSSonic Zhang 				desc->name, desc->mux_owner, owner);
138fa76a3dbSSonic Zhang 			goto out;
139fa76a3dbSSonic Zhang 		}
1400e3db173SStephen Warren 
141b1eb8fabSVladimir Zapolskiy 		if ((gpio_range || ops->strict) && desc->gpio_owner) {
142b1eb8fabSVladimir Zapolskiy 			dev_err(pctldev->dev,
143b1eb8fabSVladimir Zapolskiy 				"pin %s already requested by %s; cannot claim for %s\n",
144b1eb8fabSVladimir Zapolskiy 				desc->name, desc->gpio_owner, owner);
145b1eb8fabSVladimir Zapolskiy 			goto out;
146b1eb8fabSVladimir Zapolskiy 		}
147b1eb8fabSVladimir Zapolskiy 
148b1eb8fabSVladimir Zapolskiy 		if (gpio_range) {
149652162d4SStephen Warren 			desc->gpio_owner = owner;
150652162d4SStephen Warren 		} else {
151652162d4SStephen Warren 			desc->mux_usecount++;
152652162d4SStephen Warren 			if (desc->mux_usecount > 1)
1530e3db173SStephen Warren 				return 0;
1540e3db173SStephen Warren 
155652162d4SStephen Warren 			desc->mux_owner = owner;
156652162d4SStephen Warren 		}
157*2da32aedSMukesh Ojha 	}
1582744e8afSLinus Walleij 
1592744e8afSLinus Walleij 	/* Let each pin increase references to this module */
1602744e8afSLinus Walleij 	if (!try_module_get(pctldev->owner)) {
16151cd24eeSStephen Warren 		dev_err(pctldev->dev,
1622744e8afSLinus Walleij 			"could not increase module refcount for pin %d\n",
1632744e8afSLinus Walleij 			pin);
1642744e8afSLinus Walleij 		status = -EINVAL;
1652744e8afSLinus Walleij 		goto out_free_pin;
1662744e8afSLinus Walleij 	}
1672744e8afSLinus Walleij 
1682744e8afSLinus Walleij 	/*
1692744e8afSLinus Walleij 	 * If there is no kind of request function for the pin we just assume
1702744e8afSLinus Walleij 	 * we got it by default and proceed.
1712744e8afSLinus Walleij 	 */
1723712a3c4SStephen Warren 	if (gpio_range && ops->gpio_request_enable)
1732744e8afSLinus Walleij 		/* This requests and enables a single GPIO pin */
1742744e8afSLinus Walleij 		status = ops->gpio_request_enable(pctldev, gpio_range, pin);
1752744e8afSLinus Walleij 	else if (ops->request)
1762744e8afSLinus Walleij 		status = ops->request(pctldev, pin);
1772744e8afSLinus Walleij 	else
1782744e8afSLinus Walleij 		status = 0;
1792744e8afSLinus Walleij 
1800e3db173SStephen Warren 	if (status) {
181d4705316SStephen Warren 		dev_err(pctldev->dev, "request() failed for pin %d\n", pin);
1820e3db173SStephen Warren 		module_put(pctldev->owner);
1830e3db173SStephen Warren 	}
1840e3db173SStephen Warren 
1852744e8afSLinus Walleij out_free_pin:
1860e3db173SStephen Warren 	if (status) {
187*2da32aedSMukesh Ojha 		scoped_guard(mutex, &desc->mux_lock) {
188652162d4SStephen Warren 			if (gpio_range) {
189652162d4SStephen Warren 				desc->gpio_owner = NULL;
190652162d4SStephen Warren 			} else {
191652162d4SStephen Warren 				desc->mux_usecount--;
192652162d4SStephen Warren 				if (!desc->mux_usecount)
193652162d4SStephen Warren 					desc->mux_owner = NULL;
194652162d4SStephen Warren 			}
1950e3db173SStephen Warren 		}
196*2da32aedSMukesh Ojha 	}
1972744e8afSLinus Walleij out:
1982744e8afSLinus Walleij 	if (status)
19951cd24eeSStephen Warren 		dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
2003cc70ed3SStephen Warren 			pin, owner, status);
2012744e8afSLinus Walleij 
2022744e8afSLinus Walleij 	return status;
2032744e8afSLinus Walleij }
2042744e8afSLinus Walleij 
2052744e8afSLinus Walleij /**
2062744e8afSLinus Walleij  * pin_free() - release a single muxed in pin so something else can be muxed
2072744e8afSLinus Walleij  * @pctldev: pin controller device handling this pin
2082744e8afSLinus Walleij  * @pin: the pin to free
2093712a3c4SStephen Warren  * @gpio_range: the range matching the GPIO pin if this is a request for a
2103712a3c4SStephen Warren  *	single GPIO pin
211336cdba0SLinus Walleij  *
2123cc70ed3SStephen Warren  * This function returns a pointer to the previous owner. This is used
2133cc70ed3SStephen Warren  * for callers that dynamically allocate an owner name so it can be freed
214336cdba0SLinus Walleij  * once the pin is free. This is done for GPIO request functions.
2152744e8afSLinus Walleij  */
pin_free(struct pinctrl_dev * pctldev,int pin,struct pinctrl_gpio_range * gpio_range)2163712a3c4SStephen Warren static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
2173712a3c4SStephen Warren 			    struct pinctrl_gpio_range *gpio_range)
2182744e8afSLinus Walleij {
2192744e8afSLinus Walleij 	const struct pinmux_ops *ops = pctldev->desc->pmxops;
2202744e8afSLinus Walleij 	struct pin_desc *desc;
2213cc70ed3SStephen Warren 	const char *owner;
2222744e8afSLinus Walleij 
2232744e8afSLinus Walleij 	desc = pin_desc_get(pctldev, pin);
2242744e8afSLinus Walleij 	if (desc == NULL) {
22551cd24eeSStephen Warren 		dev_err(pctldev->dev,
2262744e8afSLinus Walleij 			"pin is not registered so it cannot be freed\n");
2273712a3c4SStephen Warren 		return NULL;
2282744e8afSLinus Walleij 	}
2292744e8afSLinus Walleij 
230*2da32aedSMukesh Ojha 	scoped_guard(mutex, &desc->mux_lock) {
231652162d4SStephen Warren 		if (!gpio_range) {
232740924a2SRichard Genoud 			/*
233740924a2SRichard Genoud 			 * A pin should not be freed more times than allocated.
234740924a2SRichard Genoud 			 */
235740924a2SRichard Genoud 			if (WARN_ON(!desc->mux_usecount))
236740924a2SRichard Genoud 				return NULL;
237652162d4SStephen Warren 			desc->mux_usecount--;
238652162d4SStephen Warren 			if (desc->mux_usecount)
2390e3db173SStephen Warren 				return NULL;
240652162d4SStephen Warren 		}
241*2da32aedSMukesh Ojha 	}
2420e3db173SStephen Warren 
2433712a3c4SStephen Warren 	/*
2443712a3c4SStephen Warren 	 * If there is no kind of request function for the pin we just assume
2453712a3c4SStephen Warren 	 * we got it by default and proceed.
2463712a3c4SStephen Warren 	 */
2473712a3c4SStephen Warren 	if (gpio_range && ops->gpio_disable_free)
2483712a3c4SStephen Warren 		ops->gpio_disable_free(pctldev, gpio_range, pin);
2493712a3c4SStephen Warren 	else if (ops->free)
2502744e8afSLinus Walleij 		ops->free(pctldev, pin);
2512744e8afSLinus Walleij 
252*2da32aedSMukesh Ojha 	scoped_guard(mutex, &desc->mux_lock) {
253652162d4SStephen Warren 		if (gpio_range) {
254652162d4SStephen Warren 			owner = desc->gpio_owner;
255652162d4SStephen Warren 			desc->gpio_owner = NULL;
256652162d4SStephen Warren 		} else {
257652162d4SStephen Warren 			owner = desc->mux_owner;
258652162d4SStephen Warren 			desc->mux_owner = NULL;
259ba110d90SStephen Warren 			desc->mux_setting = NULL;
260652162d4SStephen Warren 		}
261*2da32aedSMukesh Ojha 	}
262652162d4SStephen Warren 
2632744e8afSLinus Walleij 	module_put(pctldev->owner);
2643712a3c4SStephen Warren 
2653cc70ed3SStephen Warren 	return owner;
2662744e8afSLinus Walleij }
2672744e8afSLinus Walleij 
2682744e8afSLinus Walleij /**
269befe5bdfSLinus Walleij  * pinmux_request_gpio() - request pinmuxing for a GPIO pin
270befe5bdfSLinus Walleij  * @pctldev: pin controller device affected
271befe5bdfSLinus Walleij  * @pin: the pin to mux in for GPIO
272befe5bdfSLinus Walleij  * @range: the applicable GPIO range
273d340351fSLee Jones  * @gpio: number of requested GPIO
2742744e8afSLinus Walleij  */
pinmux_request_gpio(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned pin,unsigned gpio)275befe5bdfSLinus Walleij int pinmux_request_gpio(struct pinctrl_dev *pctldev,
276befe5bdfSLinus Walleij 			struct pinctrl_gpio_range *range,
277befe5bdfSLinus Walleij 			unsigned pin, unsigned gpio)
2782744e8afSLinus Walleij {
2793cc70ed3SStephen Warren 	const char *owner;
2802744e8afSLinus Walleij 	int ret;
2812744e8afSLinus Walleij 
2822744e8afSLinus Walleij 	/* Conjure some name stating what chip and pin this is taken by */
28323a895aeSThomas Petazzoni 	owner = kasprintf(GFP_KERNEL, "%s:%d", range->name, gpio);
2843cc70ed3SStephen Warren 	if (!owner)
2851fb1f054SMasahiro Yamada 		return -ENOMEM;
2865d2eaf80SStephen Warren 
2873cc70ed3SStephen Warren 	ret = pin_request(pctldev, pin, owner, range);
2885d2eaf80SStephen Warren 	if (ret < 0)
2893cc70ed3SStephen Warren 		kfree(owner);
2905d2eaf80SStephen Warren 
2915d2eaf80SStephen Warren 	return ret;
2922744e8afSLinus Walleij }
2932744e8afSLinus Walleij 
2942744e8afSLinus Walleij /**
295befe5bdfSLinus Walleij  * pinmux_free_gpio() - release a pin from GPIO muxing
296befe5bdfSLinus Walleij  * @pctldev: the pin controller device for the pin
297befe5bdfSLinus Walleij  * @pin: the affected currently GPIO-muxed in pin
298befe5bdfSLinus Walleij  * @range: applicable GPIO range
2992744e8afSLinus Walleij  */
pinmux_free_gpio(struct pinctrl_dev * pctldev,unsigned pin,struct pinctrl_gpio_range * range)300befe5bdfSLinus Walleij void pinmux_free_gpio(struct pinctrl_dev *pctldev, unsigned pin,
301befe5bdfSLinus Walleij 		      struct pinctrl_gpio_range *range)
3022744e8afSLinus Walleij {
3033cc70ed3SStephen Warren 	const char *owner;
3042744e8afSLinus Walleij 
3053cc70ed3SStephen Warren 	owner = pin_free(pctldev, pin, range);
3063cc70ed3SStephen Warren 	kfree(owner);
3072744e8afSLinus Walleij }
3082744e8afSLinus Walleij 
309befe5bdfSLinus Walleij /**
310befe5bdfSLinus Walleij  * pinmux_gpio_direction() - set the direction of a single muxed-in GPIO pin
311befe5bdfSLinus Walleij  * @pctldev: the pin controller handling this pin
312befe5bdfSLinus Walleij  * @range: applicable GPIO range
313befe5bdfSLinus Walleij  * @pin: the affected GPIO pin in this controller
314befe5bdfSLinus Walleij  * @input: true if we set the pin as input, false for output
315befe5bdfSLinus Walleij  */
pinmux_gpio_direction(struct pinctrl_dev * pctldev,struct pinctrl_gpio_range * range,unsigned pin,bool input)316befe5bdfSLinus Walleij int pinmux_gpio_direction(struct pinctrl_dev *pctldev,
317befe5bdfSLinus Walleij 			  struct pinctrl_gpio_range *range,
318befe5bdfSLinus Walleij 			  unsigned pin, bool input)
319542e704fSLinus Walleij {
320542e704fSLinus Walleij 	const struct pinmux_ops *ops;
321542e704fSLinus Walleij 	int ret;
322542e704fSLinus Walleij 
323542e704fSLinus Walleij 	ops = pctldev->desc->pmxops;
324542e704fSLinus Walleij 
325542e704fSLinus Walleij 	if (ops->gpio_set_direction)
326542e704fSLinus Walleij 		ret = ops->gpio_set_direction(pctldev, range, pin, input);
327542e704fSLinus Walleij 	else
328542e704fSLinus Walleij 		ret = 0;
329542e704fSLinus Walleij 
330542e704fSLinus Walleij 	return ret;
331542e704fSLinus Walleij }
332542e704fSLinus Walleij 
pinmux_func_name_to_selector(struct pinctrl_dev * pctldev,const char * function)3337ecdb16fSStephen Warren static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
3347ecdb16fSStephen Warren 					const char *function)
3352744e8afSLinus Walleij {
3362744e8afSLinus Walleij 	const struct pinmux_ops *ops = pctldev->desc->pmxops;
337d1e90e9eSViresh Kumar 	unsigned nfuncs = ops->get_functions_count(pctldev);
3382744e8afSLinus Walleij 	unsigned selector = 0;
3392744e8afSLinus Walleij 
3402744e8afSLinus Walleij 	/* See if this pctldev has this function */
341d1e90e9eSViresh Kumar 	while (selector < nfuncs) {
342163dc9f3SMasahiro Yamada 		const char *fname = ops->get_function_name(pctldev, selector);
3432744e8afSLinus Walleij 
3447ecdb16fSStephen Warren 		if (!strcmp(function, fname))
3457ecdb16fSStephen Warren 			return selector;
3462744e8afSLinus Walleij 
3472744e8afSLinus Walleij 		selector++;
3482744e8afSLinus Walleij 	}
3492744e8afSLinus Walleij 
3502744e8afSLinus Walleij 	return -EINVAL;
3512744e8afSLinus Walleij }
3522744e8afSLinus Walleij 
pinmux_map_to_setting(const struct pinctrl_map * map,struct pinctrl_setting * setting)3533f713b7cSMasahiro Yamada int pinmux_map_to_setting(const struct pinctrl_map *map,
3547ecdb16fSStephen Warren 			  struct pinctrl_setting *setting)
3552744e8afSLinus Walleij {
3567ecdb16fSStephen Warren 	struct pinctrl_dev *pctldev = setting->pctldev;
3577ecdb16fSStephen Warren 	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
3587ecdb16fSStephen Warren 	char const * const *groups;
3597ecdb16fSStephen Warren 	unsigned num_groups;
3602744e8afSLinus Walleij 	int ret;
3617ecdb16fSStephen Warren 	const char *group;
3622744e8afSLinus Walleij 
363ad8bb720SDong Aisheng 	if (!pmxops) {
364ad8bb720SDong Aisheng 		dev_err(pctldev->dev, "does not support mux function\n");
365ad8bb720SDong Aisheng 		return -EINVAL;
366ad8bb720SDong Aisheng 	}
367ad8bb720SDong Aisheng 
36815f70e1bSJohn Crispin 	ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
369ad6e1107SJohn Crispin 	if (ret < 0) {
370ad6e1107SJohn Crispin 		dev_err(pctldev->dev, "invalid function %s in map table\n",
371ad6e1107SJohn Crispin 			map->data.mux.function);
37215f70e1bSJohn Crispin 		return ret;
373ad6e1107SJohn Crispin 	}
37415f70e1bSJohn Crispin 	setting->data.mux.func = ret;
3752744e8afSLinus Walleij 
3761e2082b5SStephen Warren 	ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
3777ecdb16fSStephen Warren 					  &groups, &num_groups);
378ad6e1107SJohn Crispin 	if (ret < 0) {
379ad6e1107SJohn Crispin 		dev_err(pctldev->dev, "can't query groups for function %s\n",
380ad6e1107SJohn Crispin 			map->data.mux.function);
3812744e8afSLinus Walleij 		return ret;
382ad6e1107SJohn Crispin 	}
383ad6e1107SJohn Crispin 	if (!num_groups) {
384ad6e1107SJohn Crispin 		dev_err(pctldev->dev,
385ad6e1107SJohn Crispin 			"function %s can't be selected on any group\n",
386ad6e1107SJohn Crispin 			map->data.mux.function);
3877ecdb16fSStephen Warren 		return -EINVAL;
388ad6e1107SJohn Crispin 	}
3891e2082b5SStephen Warren 	if (map->data.mux.group) {
3901e2082b5SStephen Warren 		group = map->data.mux.group;
391dff43594SAndy Shevchenko 		ret = match_string(groups, num_groups, group);
392dff43594SAndy Shevchenko 		if (ret < 0) {
393ad6e1107SJohn Crispin 			dev_err(pctldev->dev,
394ad6e1107SJohn Crispin 				"invalid group \"%s\" for function \"%s\"\n",
395ad6e1107SJohn Crispin 				group, map->data.mux.function);
396dff43594SAndy Shevchenko 			return ret;
397ad6e1107SJohn Crispin 		}
3987ecdb16fSStephen Warren 	} else {
3997ecdb16fSStephen Warren 		group = groups[0];
4007ecdb16fSStephen Warren 	}
4017ecdb16fSStephen Warren 
40215f70e1bSJohn Crispin 	ret = pinctrl_get_group_selector(pctldev, group);
403ad6e1107SJohn Crispin 	if (ret < 0) {
404ad6e1107SJohn Crispin 		dev_err(pctldev->dev, "invalid group %s in map table\n",
405ad6e1107SJohn Crispin 			map->data.mux.group);
40615f70e1bSJohn Crispin 		return ret;
407ad6e1107SJohn Crispin 	}
40815f70e1bSJohn Crispin 	setting->data.mux.group = ret;
4097ecdb16fSStephen Warren 
410befe5bdfSLinus Walleij 	return 0;
411befe5bdfSLinus Walleij }
412befe5bdfSLinus Walleij 
pinmux_free_setting(const struct pinctrl_setting * setting)4133f713b7cSMasahiro Yamada void pinmux_free_setting(const struct pinctrl_setting *setting)
4142744e8afSLinus Walleij {
4151a78958dSLinus Walleij 	/* This function is currently unused */
4167ecdb16fSStephen Warren }
4177ecdb16fSStephen Warren 
pinmux_enable_setting(const struct pinctrl_setting * setting)4183f713b7cSMasahiro Yamada int pinmux_enable_setting(const struct pinctrl_setting *setting)
4192744e8afSLinus Walleij {
4207ecdb16fSStephen Warren 	struct pinctrl_dev *pctldev = setting->pctldev;
421ba110d90SStephen Warren 	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
4222744e8afSLinus Walleij 	const struct pinmux_ops *ops = pctldev->desc->pmxops;
423e5b3b2d9SAntoine Ténart 	int ret = 0;
424e5b3b2d9SAntoine Ténart 	const unsigned *pins = NULL;
425e5b3b2d9SAntoine Ténart 	unsigned num_pins = 0;
426ba110d90SStephen Warren 	int i;
427ba110d90SStephen Warren 	struct pin_desc *desc;
428ba110d90SStephen Warren 
429e5b3b2d9SAntoine Ténart 	if (pctlops->get_group_pins)
430ba110d90SStephen Warren 		ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
431ba110d90SStephen Warren 					      &pins, &num_pins);
432e5b3b2d9SAntoine Ténart 
433ba110d90SStephen Warren 	if (ret) {
4341c8e7944SLinus Walleij 		const char *gname;
4351c8e7944SLinus Walleij 
436ba110d90SStephen Warren 		/* errors only affect debug data, so just warn */
4371c8e7944SLinus Walleij 		gname = pctlops->get_group_name(pctldev,
438ba110d90SStephen Warren 						setting->data.mux.group);
4391c8e7944SLinus Walleij 		dev_warn(pctldev->dev,
4401c8e7944SLinus Walleij 			 "could not get pins for group %s\n",
4411c8e7944SLinus Walleij 			 gname);
442ba110d90SStephen Warren 		num_pins = 0;
443ba110d90SStephen Warren 	}
444ba110d90SStephen Warren 
4451a78958dSLinus Walleij 	/* Try to allocate all pins in this group, one by one */
4461a78958dSLinus Walleij 	for (i = 0; i < num_pins; i++) {
4471a78958dSLinus Walleij 		ret = pin_request(pctldev, pins[i], setting->dev_name, NULL);
4481a78958dSLinus Walleij 		if (ret) {
4491c8e7944SLinus Walleij 			const char *gname;
4501c8e7944SLinus Walleij 			const char *pname;
4511c8e7944SLinus Walleij 
4521c8e7944SLinus Walleij 			desc = pin_desc_get(pctldev, pins[i]);
4531c8e7944SLinus Walleij 			pname = desc ? desc->name : "non-existing";
4541c8e7944SLinus Walleij 			gname = pctlops->get_group_name(pctldev,
4551c8e7944SLinus Walleij 						setting->data.mux.group);
4561a78958dSLinus Walleij 			dev_err(pctldev->dev,
4571c8e7944SLinus Walleij 				"could not request pin %d (%s) from group %s "
4581c8e7944SLinus Walleij 				" on device %s\n",
4591c8e7944SLinus Walleij 				pins[i], pname, gname,
4601c8e7944SLinus Walleij 				pinctrl_dev_get_name(pctldev));
461e38d457dSAxel Lin 			goto err_pin_request;
4621a78958dSLinus Walleij 		}
4631a78958dSLinus Walleij 	}
4641a78958dSLinus Walleij 
4651a78958dSLinus Walleij 	/* Now that we have acquired the pins, encode the mux setting */
466ba110d90SStephen Warren 	for (i = 0; i < num_pins; i++) {
467ba110d90SStephen Warren 		desc = pin_desc_get(pctldev, pins[i]);
468ba110d90SStephen Warren 		if (desc == NULL) {
469ba110d90SStephen Warren 			dev_warn(pctldev->dev,
470ba110d90SStephen Warren 				 "could not get pin desc for pin %d\n",
471ba110d90SStephen Warren 				 pins[i]);
472ba110d90SStephen Warren 			continue;
473ba110d90SStephen Warren 		}
474*2da32aedSMukesh Ojha 		scoped_guard(mutex, &desc->mux_lock)
475ba110d90SStephen Warren 			desc->mux_setting = &(setting->data.mux);
476ba110d90SStephen Warren 	}
4772744e8afSLinus Walleij 
47803e9f0caSLinus Walleij 	ret = ops->set_mux(pctldev, setting->data.mux.func,
4791e2082b5SStephen Warren 			   setting->data.mux.group);
480e38d457dSAxel Lin 
481e38d457dSAxel Lin 	if (ret)
48203e9f0caSLinus Walleij 		goto err_set_mux;
483e38d457dSAxel Lin 
484e38d457dSAxel Lin 	return 0;
485e38d457dSAxel Lin 
48603e9f0caSLinus Walleij err_set_mux:
487e38d457dSAxel Lin 	for (i = 0; i < num_pins; i++) {
488e38d457dSAxel Lin 		desc = pin_desc_get(pctldev, pins[i]);
489*2da32aedSMukesh Ojha 		if (desc) {
490*2da32aedSMukesh Ojha 			scoped_guard(mutex, &desc->mux_lock)
491e38d457dSAxel Lin 				desc->mux_setting = NULL;
492e38d457dSAxel Lin 		}
493*2da32aedSMukesh Ojha 	}
494e38d457dSAxel Lin err_pin_request:
495e38d457dSAxel Lin 	/* On error release all taken pins */
496e38d457dSAxel Lin 	while (--i >= 0)
497e38d457dSAxel Lin 		pin_free(pctldev, pins[i], NULL);
498e38d457dSAxel Lin 
499e38d457dSAxel Lin 	return ret;
5002744e8afSLinus Walleij }
5017ecdb16fSStephen Warren 
pinmux_disable_setting(const struct pinctrl_setting * setting)5023f713b7cSMasahiro Yamada void pinmux_disable_setting(const struct pinctrl_setting *setting)
5037ecdb16fSStephen Warren {
5047ecdb16fSStephen Warren 	struct pinctrl_dev *pctldev = setting->pctldev;
505ba110d90SStephen Warren 	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
506e5b3b2d9SAntoine Ténart 	int ret = 0;
507e5b3b2d9SAntoine Ténart 	const unsigned *pins = NULL;
508e5b3b2d9SAntoine Ténart 	unsigned num_pins = 0;
509ba110d90SStephen Warren 	int i;
510ba110d90SStephen Warren 	struct pin_desc *desc;
511*2da32aedSMukesh Ojha 	bool is_equal;
512ba110d90SStephen Warren 
513e5b3b2d9SAntoine Ténart 	if (pctlops->get_group_pins)
514ba110d90SStephen Warren 		ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
515ba110d90SStephen Warren 					      &pins, &num_pins);
516ba110d90SStephen Warren 	if (ret) {
5171c8e7944SLinus Walleij 		const char *gname;
5181c8e7944SLinus Walleij 
519ba110d90SStephen Warren 		/* errors only affect debug data, so just warn */
5201c8e7944SLinus Walleij 		gname = pctlops->get_group_name(pctldev,
521ba110d90SStephen Warren 						setting->data.mux.group);
5221c8e7944SLinus Walleij 		dev_warn(pctldev->dev,
5231c8e7944SLinus Walleij 			 "could not get pins for group %s\n",
5241c8e7944SLinus Walleij 			 gname);
525ba110d90SStephen Warren 		num_pins = 0;
526ba110d90SStephen Warren 	}
527ba110d90SStephen Warren 
5281a78958dSLinus Walleij 	/* Flag the descs that no setting is active */
529ba110d90SStephen Warren 	for (i = 0; i < num_pins; i++) {
530ba110d90SStephen Warren 		desc = pin_desc_get(pctldev, pins[i]);
531ba110d90SStephen Warren 		if (desc == NULL) {
532ba110d90SStephen Warren 			dev_warn(pctldev->dev,
533ba110d90SStephen Warren 				 "could not get pin desc for pin %d\n",
534ba110d90SStephen Warren 				 pins[i]);
535ba110d90SStephen Warren 			continue;
536ba110d90SStephen Warren 		}
537*2da32aedSMukesh Ojha 		scoped_guard(mutex, &desc->mux_lock)
538*2da32aedSMukesh Ojha 			is_equal = (desc->mux_setting == &(setting->data.mux));
539*2da32aedSMukesh Ojha 
540*2da32aedSMukesh Ojha 		if (is_equal) {
5411a78958dSLinus Walleij 			pin_free(pctldev, pins[i], NULL);
5421c8e7944SLinus Walleij 		} else {
5431c8e7944SLinus Walleij 			const char *gname;
5441c8e7944SLinus Walleij 
5451c8e7944SLinus Walleij 			gname = pctlops->get_group_name(pctldev,
5461c8e7944SLinus Walleij 						setting->data.mux.group);
5471c8e7944SLinus Walleij 			dev_warn(pctldev->dev,
5481c8e7944SLinus Walleij 				 "not freeing pin %d (%s) as part of "
5491c8e7944SLinus Walleij 				 "deactivating group %s - it is already "
5501c8e7944SLinus Walleij 				 "used for some other setting",
551808e657cSMichael Opdenacker 				 pins[i], desc->name, gname);
552744f0a9aSSonic Zhang 		}
553744f0a9aSSonic Zhang 	}
5542744e8afSLinus Walleij }
5552744e8afSLinus Walleij 
5562744e8afSLinus Walleij #ifdef CONFIG_DEBUG_FS
5572744e8afSLinus Walleij 
5582744e8afSLinus Walleij /* Called from pincontrol core */
pinmux_functions_show(struct seq_file * s,void * what)5592744e8afSLinus Walleij static int pinmux_functions_show(struct seq_file *s, void *what)
5602744e8afSLinus Walleij {
5612744e8afSLinus Walleij 	struct pinctrl_dev *pctldev = s->private;
5622744e8afSLinus Walleij 	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
563ad8bb720SDong Aisheng 	unsigned nfuncs;
5642744e8afSLinus Walleij 	unsigned func_selector = 0;
5652744e8afSLinus Walleij 
566ad8bb720SDong Aisheng 	if (!pmxops)
567ad8bb720SDong Aisheng 		return 0;
56857b676f9SStephen Warren 
56942fed7baSPatrice Chotard 	mutex_lock(&pctldev->mutex);
570ad8bb720SDong Aisheng 	nfuncs = pmxops->get_functions_count(pctldev);
571d1e90e9eSViresh Kumar 	while (func_selector < nfuncs) {
5722744e8afSLinus Walleij 		const char *func = pmxops->get_function_name(pctldev,
5732744e8afSLinus Walleij 							  func_selector);
5742744e8afSLinus Walleij 		const char * const *groups;
5752744e8afSLinus Walleij 		unsigned num_groups;
5762744e8afSLinus Walleij 		int ret;
5772744e8afSLinus Walleij 		int i;
5782744e8afSLinus Walleij 
5792744e8afSLinus Walleij 		ret = pmxops->get_function_groups(pctldev, func_selector,
5802744e8afSLinus Walleij 						  &groups, &num_groups);
5819d7ebbbfSLudovic Desroches 		if (ret) {
5822744e8afSLinus Walleij 			seq_printf(s, "function %s: COULD NOT GET GROUPS\n",
5832744e8afSLinus Walleij 				   func);
5849d7ebbbfSLudovic Desroches 			func_selector++;
5859d7ebbbfSLudovic Desroches 			continue;
5869d7ebbbfSLudovic Desroches 		}
5872744e8afSLinus Walleij 
5883bbf9b89SDrew Fustini 		seq_printf(s, "function %d: %s, groups = [ ", func_selector, func);
5892744e8afSLinus Walleij 		for (i = 0; i < num_groups; i++)
5902744e8afSLinus Walleij 			seq_printf(s, "%s ", groups[i]);
5912744e8afSLinus Walleij 		seq_puts(s, "]\n");
5922744e8afSLinus Walleij 
5932744e8afSLinus Walleij 		func_selector++;
5942744e8afSLinus Walleij 	}
5952744e8afSLinus Walleij 
59642fed7baSPatrice Chotard 	mutex_unlock(&pctldev->mutex);
59757b676f9SStephen Warren 
5982744e8afSLinus Walleij 	return 0;
5992744e8afSLinus Walleij }
6002744e8afSLinus Walleij 
pinmux_pins_show(struct seq_file * s,void * what)6012744e8afSLinus Walleij static int pinmux_pins_show(struct seq_file *s, void *what)
6022744e8afSLinus Walleij {
6032744e8afSLinus Walleij 	struct pinctrl_dev *pctldev = s->private;
604ba110d90SStephen Warren 	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
605ba110d90SStephen Warren 	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
606706e8520SChanho Park 	unsigned i, pin;
6072744e8afSLinus Walleij 
608ad8bb720SDong Aisheng 	if (!pmxops)
609ad8bb720SDong Aisheng 		return 0;
610ad8bb720SDong Aisheng 
6112744e8afSLinus Walleij 	seq_puts(s, "Pinmux settings per pin\n");
61281508855SLinus Walleij 	if (pmxops->strict)
61381508855SLinus Walleij 		seq_puts(s,
61481508855SLinus Walleij 		 "Format: pin (name): mux_owner|gpio_owner (strict) hog?\n");
61581508855SLinus Walleij 	else
61681508855SLinus Walleij 		seq_puts(s,
61781508855SLinus Walleij 		"Format: pin (name): mux_owner gpio_owner hog?\n");
6182744e8afSLinus Walleij 
61942fed7baSPatrice Chotard 	mutex_lock(&pctldev->mutex);
62057b676f9SStephen Warren 
621706e8520SChanho Park 	/* The pin number can be retrived from the pin controller descriptor */
622706e8520SChanho Park 	for (i = 0; i < pctldev->desc->npins; i++) {
6232744e8afSLinus Walleij 		struct pin_desc *desc;
6241cf94c45SLinus Walleij 		bool is_hog = false;
6252744e8afSLinus Walleij 
626706e8520SChanho Park 		pin = pctldev->desc->pins[i].number;
6272744e8afSLinus Walleij 		desc = pin_desc_get(pctldev, pin);
628706e8520SChanho Park 		/* Skip if we cannot search the pin */
6292744e8afSLinus Walleij 		if (desc == NULL)
6302744e8afSLinus Walleij 			continue;
6312744e8afSLinus Walleij 
632*2da32aedSMukesh Ojha 		scoped_guard(mutex, &desc->mux_lock) {
633652162d4SStephen Warren 			if (desc->mux_owner &&
634652162d4SStephen Warren 			    !strcmp(desc->mux_owner, pinctrl_dev_get_name(pctldev)))
6351cf94c45SLinus Walleij 				is_hog = true;
6361cf94c45SLinus Walleij 
63781508855SLinus Walleij 			if (pmxops->strict) {
63881508855SLinus Walleij 				if (desc->mux_owner)
63981508855SLinus Walleij 					seq_printf(s, "pin %d (%s): device %s%s",
640cf9d994dSMasahiro Yamada 						   pin, desc->name, desc->mux_owner,
64181508855SLinus Walleij 						   is_hog ? " (HOG)" : "");
64281508855SLinus Walleij 				else if (desc->gpio_owner)
64381508855SLinus Walleij 					seq_printf(s, "pin %d (%s): GPIO %s",
644cf9d994dSMasahiro Yamada 						   pin, desc->name, desc->gpio_owner);
64581508855SLinus Walleij 				else
64681508855SLinus Walleij 					seq_printf(s, "pin %d (%s): UNCLAIMED",
647cf9d994dSMasahiro Yamada 						   pin, desc->name);
64881508855SLinus Walleij 			} else {
64981508855SLinus Walleij 				/* For non-strict controllers */
650cf9d994dSMasahiro Yamada 				seq_printf(s, "pin %d (%s): %s %s%s", pin, desc->name,
651652162d4SStephen Warren 					   desc->mux_owner ? desc->mux_owner
652652162d4SStephen Warren 					   : "(MUX UNCLAIMED)",
653652162d4SStephen Warren 					   desc->gpio_owner ? desc->gpio_owner
654652162d4SStephen Warren 					   : "(GPIO UNCLAIMED)",
6551cf94c45SLinus Walleij 					   is_hog ? " (HOG)" : "");
65681508855SLinus Walleij 			}
657ba110d90SStephen Warren 
65881508855SLinus Walleij 			/* If mux: print function+group claiming the pin */
659ba110d90SStephen Warren 			if (desc->mux_setting)
660ba110d90SStephen Warren 				seq_printf(s, " function %s group %s\n",
661ba110d90SStephen Warren 					   pmxops->get_function_name(pctldev,
662ba110d90SStephen Warren 						desc->mux_setting->func),
663ba110d90SStephen Warren 					   pctlops->get_group_name(pctldev,
664ba110d90SStephen Warren 						desc->mux_setting->group));
665ba110d90SStephen Warren 			else
666ffd10c2eSMarkus Elfring 				seq_putc(s, '\n');
6672744e8afSLinus Walleij 		}
668*2da32aedSMukesh Ojha 	}
6692744e8afSLinus Walleij 
67042fed7baSPatrice Chotard 	mutex_unlock(&pctldev->mutex);
67157b676f9SStephen Warren 
6722744e8afSLinus Walleij 	return 0;
6732744e8afSLinus Walleij }
6742744e8afSLinus Walleij 
pinmux_show_map(struct seq_file * s,const struct pinctrl_map * map)6753f713b7cSMasahiro Yamada void pinmux_show_map(struct seq_file *s, const struct pinctrl_map *map)
6761e2082b5SStephen Warren {
6771e2082b5SStephen Warren 	seq_printf(s, "group %s\nfunction %s\n",
6781e2082b5SStephen Warren 		map->data.mux.group ? map->data.mux.group : "(default)",
6791e2082b5SStephen Warren 		map->data.mux.function);
6801e2082b5SStephen Warren }
6811e2082b5SStephen Warren 
pinmux_show_setting(struct seq_file * s,const struct pinctrl_setting * setting)6821e2082b5SStephen Warren void pinmux_show_setting(struct seq_file *s,
6833f713b7cSMasahiro Yamada 			 const struct pinctrl_setting *setting)
6842744e8afSLinus Walleij {
6857ecdb16fSStephen Warren 	struct pinctrl_dev *pctldev = setting->pctldev;
6867ecdb16fSStephen Warren 	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
6877ecdb16fSStephen Warren 	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
6882744e8afSLinus Walleij 
6891e2082b5SStephen Warren 	seq_printf(s, "group: %s (%u) function: %s (%u)\n",
6901e2082b5SStephen Warren 		   pctlops->get_group_name(pctldev, setting->data.mux.group),
6911e2082b5SStephen Warren 		   setting->data.mux.group,
6921e2082b5SStephen Warren 		   pmxops->get_function_name(pctldev, setting->data.mux.func),
6931e2082b5SStephen Warren 		   setting->data.mux.func);
6942744e8afSLinus Walleij }
6952744e8afSLinus Walleij 
6960819dc72SYangtao Li DEFINE_SHOW_ATTRIBUTE(pinmux_functions);
6970819dc72SYangtao Li DEFINE_SHOW_ATTRIBUTE(pinmux_pins);
6982744e8afSLinus Walleij 
pinmux_select(struct file * file,const char __user * user_buf,size_t len,loff_t * ppos)6996199f6beSDrew Fustini static ssize_t pinmux_select(struct file *file, const char __user *user_buf,
7006199f6beSDrew Fustini 				   size_t len, loff_t *ppos)
7016199f6beSDrew Fustini {
7026199f6beSDrew Fustini 	struct seq_file *sfile = file->private_data;
7036199f6beSDrew Fustini 	struct pinctrl_dev *pctldev = sfile->private;
7046199f6beSDrew Fustini 	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
7056199f6beSDrew Fustini 	const char *const *groups;
7066199f6beSDrew Fustini 	char *buf, *gname, *fname;
7076199f6beSDrew Fustini 	unsigned int num_groups;
7086199f6beSDrew Fustini 	int fsel, gsel, ret;
7096199f6beSDrew Fustini 
7100d8675e1SAndy Shevchenko 	buf = memdup_user_nul(user_buf, len);
7110d8675e1SAndy Shevchenko 	if (IS_ERR(buf))
7120d8675e1SAndy Shevchenko 		return PTR_ERR(buf);
7136199f6beSDrew Fustini 
7146199f6beSDrew Fustini 	/* remove leading and trailing spaces of input buffer */
7156199f6beSDrew Fustini 	gname = strstrip(buf);
7166199f6beSDrew Fustini 	if (*gname == '\0') {
7176199f6beSDrew Fustini 		ret = -EINVAL;
7186199f6beSDrew Fustini 		goto exit_free_buf;
7196199f6beSDrew Fustini 	}
7206199f6beSDrew Fustini 
7216199f6beSDrew Fustini 	/* find a separator which is a spacelike character */
7226199f6beSDrew Fustini 	for (fname = gname; !isspace(*fname); fname++) {
7236199f6beSDrew Fustini 		if (*fname == '\0') {
7246199f6beSDrew Fustini 			ret = -EINVAL;
7256199f6beSDrew Fustini 			goto exit_free_buf;
7266199f6beSDrew Fustini 		}
7276199f6beSDrew Fustini 	}
7286199f6beSDrew Fustini 	*fname = '\0';
7296199f6beSDrew Fustini 
7306199f6beSDrew Fustini 	/* drop extra spaces between function and group names */
7316199f6beSDrew Fustini 	fname = skip_spaces(fname + 1);
7326199f6beSDrew Fustini 	if (*fname == '\0') {
7336199f6beSDrew Fustini 		ret = -EINVAL;
7346199f6beSDrew Fustini 		goto exit_free_buf;
7356199f6beSDrew Fustini 	}
7366199f6beSDrew Fustini 
7376199f6beSDrew Fustini 	ret = pinmux_func_name_to_selector(pctldev, fname);
7386199f6beSDrew Fustini 	if (ret < 0) {
7396199f6beSDrew Fustini 		dev_err(pctldev->dev, "invalid function %s in map table\n", fname);
7406199f6beSDrew Fustini 		goto exit_free_buf;
7416199f6beSDrew Fustini 	}
7426199f6beSDrew Fustini 	fsel = ret;
7436199f6beSDrew Fustini 
7446199f6beSDrew Fustini 	ret = pmxops->get_function_groups(pctldev, fsel, &groups, &num_groups);
7456199f6beSDrew Fustini 	if (ret) {
7466199f6beSDrew Fustini 		dev_err(pctldev->dev, "no groups for function %d (%s)", fsel, fname);
7476199f6beSDrew Fustini 		goto exit_free_buf;
7486199f6beSDrew Fustini 	}
7496199f6beSDrew Fustini 
7506199f6beSDrew Fustini 	ret = match_string(groups, num_groups, gname);
7516199f6beSDrew Fustini 	if (ret < 0) {
7526199f6beSDrew Fustini 		dev_err(pctldev->dev, "invalid group %s", gname);
7536199f6beSDrew Fustini 		goto exit_free_buf;
7546199f6beSDrew Fustini 	}
7556199f6beSDrew Fustini 
7566199f6beSDrew Fustini 	ret = pinctrl_get_group_selector(pctldev, gname);
757091e81b8SAndy Shevchenko 	if (ret < 0)
7586199f6beSDrew Fustini 		goto exit_free_buf;
7596199f6beSDrew Fustini 	gsel = ret;
7606199f6beSDrew Fustini 
7616199f6beSDrew Fustini 	ret = pmxops->set_mux(pctldev, fsel, gsel);
7626199f6beSDrew Fustini 	if (ret) {
7636199f6beSDrew Fustini 		dev_err(pctldev->dev, "set_mux() failed: %d", ret);
7646199f6beSDrew Fustini 		goto exit_free_buf;
7656199f6beSDrew Fustini 	}
7666199f6beSDrew Fustini 	ret = len;
7676199f6beSDrew Fustini 
7686199f6beSDrew Fustini exit_free_buf:
7696199f6beSDrew Fustini 	kfree(buf);
7706199f6beSDrew Fustini 
7716199f6beSDrew Fustini 	return ret;
7726199f6beSDrew Fustini }
7736199f6beSDrew Fustini 
pinmux_select_open(struct inode * inode,struct file * file)7746199f6beSDrew Fustini static int pinmux_select_open(struct inode *inode, struct file *file)
7756199f6beSDrew Fustini {
7766199f6beSDrew Fustini 	return single_open(file, NULL, inode->i_private);
7776199f6beSDrew Fustini }
7786199f6beSDrew Fustini 
7796199f6beSDrew Fustini static const struct file_operations pinmux_select_ops = {
7806199f6beSDrew Fustini 	.owner = THIS_MODULE,
7816199f6beSDrew Fustini 	.open = pinmux_select_open,
7826199f6beSDrew Fustini 	.write = pinmux_select,
7836199f6beSDrew Fustini 	.llseek = no_llseek,
7846199f6beSDrew Fustini 	.release = single_release,
7856199f6beSDrew Fustini };
7866199f6beSDrew Fustini 
pinmux_init_device_debugfs(struct dentry * devroot,struct pinctrl_dev * pctldev)7872744e8afSLinus Walleij void pinmux_init_device_debugfs(struct dentry *devroot,
7882744e8afSLinus Walleij 			 struct pinctrl_dev *pctldev)
7892744e8afSLinus Walleij {
79047473813SDrew Fustini 	debugfs_create_file("pinmux-functions", 0444,
7910819dc72SYangtao Li 			    devroot, pctldev, &pinmux_functions_fops);
79247473813SDrew Fustini 	debugfs_create_file("pinmux-pins", 0444,
7930819dc72SYangtao Li 			    devroot, pctldev, &pinmux_pins_fops);
7946199f6beSDrew Fustini 	debugfs_create_file("pinmux-select", 0200,
7956199f6beSDrew Fustini 			    devroot, pctldev, &pinmux_select_ops);
7962744e8afSLinus Walleij }
7972744e8afSLinus Walleij 
7982744e8afSLinus Walleij #endif /* CONFIG_DEBUG_FS */
799a76edc89STony Lindgren 
800a76edc89STony Lindgren #ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS
801a76edc89STony Lindgren 
802a76edc89STony Lindgren /**
803a76edc89STony Lindgren  * pinmux_generic_get_function_count() - returns number of functions
804a76edc89STony Lindgren  * @pctldev: pin controller device
805a76edc89STony Lindgren  */
pinmux_generic_get_function_count(struct pinctrl_dev * pctldev)806a76edc89STony Lindgren int pinmux_generic_get_function_count(struct pinctrl_dev *pctldev)
807a76edc89STony Lindgren {
808a76edc89STony Lindgren 	return pctldev->num_functions;
809a76edc89STony Lindgren }
810a76edc89STony Lindgren EXPORT_SYMBOL_GPL(pinmux_generic_get_function_count);
811a76edc89STony Lindgren 
812a76edc89STony Lindgren /**
813a76edc89STony Lindgren  * pinmux_generic_get_function_name() - returns the function name
814a76edc89STony Lindgren  * @pctldev: pin controller device
815a76edc89STony Lindgren  * @selector: function number
816a76edc89STony Lindgren  */
817a76edc89STony Lindgren const char *
pinmux_generic_get_function_name(struct pinctrl_dev * pctldev,unsigned int selector)818a76edc89STony Lindgren pinmux_generic_get_function_name(struct pinctrl_dev *pctldev,
819a76edc89STony Lindgren 				 unsigned int selector)
820a76edc89STony Lindgren {
821a76edc89STony Lindgren 	struct function_desc *function;
822a76edc89STony Lindgren 
823a76edc89STony Lindgren 	function = radix_tree_lookup(&pctldev->pin_function_tree,
824a76edc89STony Lindgren 				     selector);
825a76edc89STony Lindgren 	if (!function)
826a76edc89STony Lindgren 		return NULL;
827a76edc89STony Lindgren 
828a76edc89STony Lindgren 	return function->name;
829a76edc89STony Lindgren }
830a76edc89STony Lindgren EXPORT_SYMBOL_GPL(pinmux_generic_get_function_name);
831a76edc89STony Lindgren 
832a76edc89STony Lindgren /**
833a76edc89STony Lindgren  * pinmux_generic_get_function_groups() - gets the function groups
834a76edc89STony Lindgren  * @pctldev: pin controller device
835a76edc89STony Lindgren  * @selector: function number
836a76edc89STony Lindgren  * @groups: array of pin groups
837a76edc89STony Lindgren  * @num_groups: number of pin groups
838a76edc89STony Lindgren  */
pinmux_generic_get_function_groups(struct pinctrl_dev * pctldev,unsigned int selector,const char * const ** groups,unsigned * const num_groups)839a76edc89STony Lindgren int pinmux_generic_get_function_groups(struct pinctrl_dev *pctldev,
840a76edc89STony Lindgren 				       unsigned int selector,
841a76edc89STony Lindgren 				       const char * const **groups,
842a76edc89STony Lindgren 				       unsigned * const num_groups)
843a76edc89STony Lindgren {
844a76edc89STony Lindgren 	struct function_desc *function;
845a76edc89STony Lindgren 
846a76edc89STony Lindgren 	function = radix_tree_lookup(&pctldev->pin_function_tree,
847a76edc89STony Lindgren 				     selector);
848a76edc89STony Lindgren 	if (!function) {
849a76edc89STony Lindgren 		dev_err(pctldev->dev, "%s could not find function%i\n",
850a76edc89STony Lindgren 			__func__, selector);
851a76edc89STony Lindgren 		return -EINVAL;
852a76edc89STony Lindgren 	}
853a76edc89STony Lindgren 	*groups = function->group_names;
854a76edc89STony Lindgren 	*num_groups = function->num_group_names;
855a76edc89STony Lindgren 
856a76edc89STony Lindgren 	return 0;
857a76edc89STony Lindgren }
858a76edc89STony Lindgren EXPORT_SYMBOL_GPL(pinmux_generic_get_function_groups);
859a76edc89STony Lindgren 
860a76edc89STony Lindgren /**
861a76edc89STony Lindgren  * pinmux_generic_get_function() - returns a function based on the number
862a76edc89STony Lindgren  * @pctldev: pin controller device
863d340351fSLee Jones  * @selector: function number
864a76edc89STony Lindgren  */
pinmux_generic_get_function(struct pinctrl_dev * pctldev,unsigned int selector)865a76edc89STony Lindgren struct function_desc *pinmux_generic_get_function(struct pinctrl_dev *pctldev,
866a76edc89STony Lindgren 						  unsigned int selector)
867a76edc89STony Lindgren {
868a76edc89STony Lindgren 	struct function_desc *function;
869a76edc89STony Lindgren 
870a76edc89STony Lindgren 	function = radix_tree_lookup(&pctldev->pin_function_tree,
871a76edc89STony Lindgren 				     selector);
872a76edc89STony Lindgren 	if (!function)
873a76edc89STony Lindgren 		return NULL;
874a76edc89STony Lindgren 
875a76edc89STony Lindgren 	return function;
876a76edc89STony Lindgren }
877a76edc89STony Lindgren EXPORT_SYMBOL_GPL(pinmux_generic_get_function);
878a76edc89STony Lindgren 
879a76edc89STony Lindgren /**
8806bffa7e1SGeert Uytterhoeven  * pinmux_generic_add_function() - adds a function group
881a76edc89STony Lindgren  * @pctldev: pin controller device
882a76edc89STony Lindgren  * @name: name of the function
883a76edc89STony Lindgren  * @groups: array of pin groups
884a76edc89STony Lindgren  * @num_groups: number of pin groups
885a76edc89STony Lindgren  * @data: pin controller driver specific data
886a76edc89STony Lindgren  */
pinmux_generic_add_function(struct pinctrl_dev * pctldev,const char * name,const char * const * groups,const unsigned int num_groups,void * data)887a76edc89STony Lindgren int pinmux_generic_add_function(struct pinctrl_dev *pctldev,
888a76edc89STony Lindgren 				const char *name,
889bd0aae66SRafał Miłecki 				const char * const *groups,
890a76edc89STony Lindgren 				const unsigned int num_groups,
891a76edc89STony Lindgren 				void *data)
892a76edc89STony Lindgren {
893a76edc89STony Lindgren 	struct function_desc *function;
8946ec89cd4SSergey Shtylyov 	int selector, error;
895f913cfceSTony Lindgren 
896f913cfceSTony Lindgren 	if (!name)
897f913cfceSTony Lindgren 		return -EINVAL;
898f913cfceSTony Lindgren 
899f913cfceSTony Lindgren 	selector = pinmux_func_name_to_selector(pctldev, name);
900f913cfceSTony Lindgren 	if (selector >= 0)
901f913cfceSTony Lindgren 		return selector;
902f913cfceSTony Lindgren 
903f913cfceSTony Lindgren 	selector = pctldev->num_functions;
904a76edc89STony Lindgren 
905a76edc89STony Lindgren 	function = devm_kzalloc(pctldev->dev, sizeof(*function), GFP_KERNEL);
906a76edc89STony Lindgren 	if (!function)
907a76edc89STony Lindgren 		return -ENOMEM;
908a76edc89STony Lindgren 
909a76edc89STony Lindgren 	function->name = name;
910a76edc89STony Lindgren 	function->group_names = groups;
911a76edc89STony Lindgren 	function->num_group_names = num_groups;
912a76edc89STony Lindgren 	function->data = data;
913a76edc89STony Lindgren 
9146ec89cd4SSergey Shtylyov 	error = radix_tree_insert(&pctldev->pin_function_tree, selector, function);
9156ec89cd4SSergey Shtylyov 	if (error)
9166ec89cd4SSergey Shtylyov 		return error;
917a76edc89STony Lindgren 
918a76edc89STony Lindgren 	pctldev->num_functions++;
919a76edc89STony Lindgren 
920f913cfceSTony Lindgren 	return selector;
921a76edc89STony Lindgren }
922a76edc89STony Lindgren EXPORT_SYMBOL_GPL(pinmux_generic_add_function);
923a76edc89STony Lindgren 
924a76edc89STony Lindgren /**
925a76edc89STony Lindgren  * pinmux_generic_remove_function() - removes a numbered function
926a76edc89STony Lindgren  * @pctldev: pin controller device
927a76edc89STony Lindgren  * @selector: function number
928a76edc89STony Lindgren  *
929a76edc89STony Lindgren  * Note that the caller must take care of locking.
930a76edc89STony Lindgren  */
pinmux_generic_remove_function(struct pinctrl_dev * pctldev,unsigned int selector)931a76edc89STony Lindgren int pinmux_generic_remove_function(struct pinctrl_dev *pctldev,
932a76edc89STony Lindgren 				   unsigned int selector)
933a76edc89STony Lindgren {
934a76edc89STony Lindgren 	struct function_desc *function;
935a76edc89STony Lindgren 
936a76edc89STony Lindgren 	function = radix_tree_lookup(&pctldev->pin_function_tree,
937a76edc89STony Lindgren 				     selector);
938a76edc89STony Lindgren 	if (!function)
939a76edc89STony Lindgren 		return -ENOENT;
940a76edc89STony Lindgren 
941a76edc89STony Lindgren 	radix_tree_delete(&pctldev->pin_function_tree, selector);
942a76edc89STony Lindgren 	devm_kfree(pctldev->dev, function);
943a76edc89STony Lindgren 
944a76edc89STony Lindgren 	pctldev->num_functions--;
945a76edc89STony Lindgren 
946a76edc89STony Lindgren 	return 0;
947a76edc89STony Lindgren }
948a76edc89STony Lindgren EXPORT_SYMBOL_GPL(pinmux_generic_remove_function);
949a76edc89STony Lindgren 
950a76edc89STony Lindgren /**
951a76edc89STony Lindgren  * pinmux_generic_free_functions() - removes all functions
952a76edc89STony Lindgren  * @pctldev: pin controller device
953a76edc89STony Lindgren  *
954664b7c47STony Lindgren  * Note that the caller must take care of locking. The pinctrl
955664b7c47STony Lindgren  * functions are allocated with devm_kzalloc() so no need to free
956664b7c47STony Lindgren  * them here.
957a76edc89STony Lindgren  */
pinmux_generic_free_functions(struct pinctrl_dev * pctldev)958a76edc89STony Lindgren void pinmux_generic_free_functions(struct pinctrl_dev *pctldev)
959a76edc89STony Lindgren {
960a76edc89STony Lindgren 	struct radix_tree_iter iter;
961906a2a39SMasahiro Yamada 	void __rcu **slot;
962a76edc89STony Lindgren 
963a76edc89STony Lindgren 	radix_tree_for_each_slot(slot, &pctldev->pin_function_tree, &iter, 0)
964664b7c47STony Lindgren 		radix_tree_delete(&pctldev->pin_function_tree, iter.index);
965a76edc89STony Lindgren 
966a76edc89STony Lindgren 	pctldev->num_functions = 0;
967a76edc89STony Lindgren }
968a76edc89STony Lindgren 
969a76edc89STony Lindgren #endif /* CONFIG_GENERIC_PINMUX_FUNCTIONS */
970