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