162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Core driver for the pin muxing portions of the pin control subsystem
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2011-2012 ST-Ericsson SA
662306a36Sopenharmony_ci * Written on behalf of Linaro for ST-Ericsson
762306a36Sopenharmony_ci * Based on bits of regulator core, gpio core and clk core
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Author: Linus Walleij <linus.walleij@linaro.org>
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci#define pr_fmt(fmt) "pinmux core: " fmt
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/ctype.h>
1662306a36Sopenharmony_ci#include <linux/debugfs.h>
1762306a36Sopenharmony_ci#include <linux/device.h>
1862306a36Sopenharmony_ci#include <linux/err.h>
1962306a36Sopenharmony_ci#include <linux/init.h>
2062306a36Sopenharmony_ci#include <linux/kernel.h>
2162306a36Sopenharmony_ci#include <linux/list.h>
2262306a36Sopenharmony_ci#include <linux/module.h>
2362306a36Sopenharmony_ci#include <linux/radix-tree.h>
2462306a36Sopenharmony_ci#include <linux/seq_file.h>
2562306a36Sopenharmony_ci#include <linux/slab.h>
2662306a36Sopenharmony_ci#include <linux/string.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include <linux/pinctrl/machine.h>
2962306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h>
3062306a36Sopenharmony_ci#include <linux/pinctrl/pinmux.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include "core.h"
3362306a36Sopenharmony_ci#include "pinmux.h"
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ciint pinmux_check_ops(struct pinctrl_dev *pctldev)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
3862306a36Sopenharmony_ci	unsigned nfuncs;
3962306a36Sopenharmony_ci	unsigned selector = 0;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	/* Check that we implement required operations */
4262306a36Sopenharmony_ci	if (!ops ||
4362306a36Sopenharmony_ci	    !ops->get_functions_count ||
4462306a36Sopenharmony_ci	    !ops->get_function_name ||
4562306a36Sopenharmony_ci	    !ops->get_function_groups ||
4662306a36Sopenharmony_ci	    !ops->set_mux) {
4762306a36Sopenharmony_ci		dev_err(pctldev->dev, "pinmux ops lacks necessary functions\n");
4862306a36Sopenharmony_ci		return -EINVAL;
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci	/* Check that all functions registered have names */
5162306a36Sopenharmony_ci	nfuncs = ops->get_functions_count(pctldev);
5262306a36Sopenharmony_ci	while (selector < nfuncs) {
5362306a36Sopenharmony_ci		const char *fname = ops->get_function_name(pctldev,
5462306a36Sopenharmony_ci							   selector);
5562306a36Sopenharmony_ci		if (!fname) {
5662306a36Sopenharmony_ci			dev_err(pctldev->dev, "pinmux ops has no name for function%u\n",
5762306a36Sopenharmony_ci				selector);
5862306a36Sopenharmony_ci			return -EINVAL;
5962306a36Sopenharmony_ci		}
6062306a36Sopenharmony_ci		selector++;
6162306a36Sopenharmony_ci	}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	return 0;
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ciint pinmux_validate_map(const struct pinctrl_map *map, int i)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	if (!map->data.mux.function) {
6962306a36Sopenharmony_ci		pr_err("failed to register map %s (%d): no function given\n",
7062306a36Sopenharmony_ci		       map->name, i);
7162306a36Sopenharmony_ci		return -EINVAL;
7262306a36Sopenharmony_ci	}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	return 0;
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/**
7862306a36Sopenharmony_ci * pinmux_can_be_used_for_gpio() - check if a specific pin
7962306a36Sopenharmony_ci *	is either muxed to a different function or used as gpio.
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * @pctldev: the associated pin controller device
8262306a36Sopenharmony_ci * @pin: the pin number in the global pin space
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci * Controllers not defined as strict will always return true,
8562306a36Sopenharmony_ci * menaning that the gpio can be used.
8662306a36Sopenharmony_ci */
8762306a36Sopenharmony_cibool pinmux_can_be_used_for_gpio(struct pinctrl_dev *pctldev, unsigned pin)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	struct pin_desc *desc = pin_desc_get(pctldev, pin);
9062306a36Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	/* Can't inspect pin, assume it can be used */
9362306a36Sopenharmony_ci	if (!desc || !ops)
9462306a36Sopenharmony_ci		return true;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	if (ops->strict && desc->mux_usecount)
9762306a36Sopenharmony_ci		return false;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	return !(ops->strict && !!desc->gpio_owner);
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/**
10362306a36Sopenharmony_ci * pin_request() - request a single pin to be muxed in, typically for GPIO
10462306a36Sopenharmony_ci * @pctldev: the associated pin controller device
10562306a36Sopenharmony_ci * @pin: the pin number in the global pin space
10662306a36Sopenharmony_ci * @owner: a representation of the owner of this pin; typically the device
10762306a36Sopenharmony_ci *	name that controls its mux function, or the requested GPIO name
10862306a36Sopenharmony_ci * @gpio_range: the range matching the GPIO pin if this is a request for a
10962306a36Sopenharmony_ci *	single GPIO pin
11062306a36Sopenharmony_ci */
11162306a36Sopenharmony_cistatic int pin_request(struct pinctrl_dev *pctldev,
11262306a36Sopenharmony_ci		       int pin, const char *owner,
11362306a36Sopenharmony_ci		       struct pinctrl_gpio_range *gpio_range)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	struct pin_desc *desc;
11662306a36Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
11762306a36Sopenharmony_ci	int status = -EINVAL;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	desc = pin_desc_get(pctldev, pin);
12062306a36Sopenharmony_ci	if (desc == NULL) {
12162306a36Sopenharmony_ci		dev_err(pctldev->dev,
12262306a36Sopenharmony_ci			"pin %d is not registered so it cannot be requested\n",
12362306a36Sopenharmony_ci			pin);
12462306a36Sopenharmony_ci		goto out;
12562306a36Sopenharmony_ci	}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
12862306a36Sopenharmony_ci		pin, desc->name, owner);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	if ((!gpio_range || ops->strict) &&
13162306a36Sopenharmony_ci	    desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
13262306a36Sopenharmony_ci		dev_err(pctldev->dev,
13362306a36Sopenharmony_ci			"pin %s already requested by %s; cannot claim for %s\n",
13462306a36Sopenharmony_ci			desc->name, desc->mux_owner, owner);
13562306a36Sopenharmony_ci		goto out;
13662306a36Sopenharmony_ci	}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	if ((gpio_range || ops->strict) && desc->gpio_owner) {
13962306a36Sopenharmony_ci		dev_err(pctldev->dev,
14062306a36Sopenharmony_ci			"pin %s already requested by %s; cannot claim for %s\n",
14162306a36Sopenharmony_ci			desc->name, desc->gpio_owner, owner);
14262306a36Sopenharmony_ci		goto out;
14362306a36Sopenharmony_ci	}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if (gpio_range) {
14662306a36Sopenharmony_ci		desc->gpio_owner = owner;
14762306a36Sopenharmony_ci	} else {
14862306a36Sopenharmony_ci		desc->mux_usecount++;
14962306a36Sopenharmony_ci		if (desc->mux_usecount > 1)
15062306a36Sopenharmony_ci			return 0;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci		desc->mux_owner = owner;
15362306a36Sopenharmony_ci	}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	/* Let each pin increase references to this module */
15662306a36Sopenharmony_ci	if (!try_module_get(pctldev->owner)) {
15762306a36Sopenharmony_ci		dev_err(pctldev->dev,
15862306a36Sopenharmony_ci			"could not increase module refcount for pin %d\n",
15962306a36Sopenharmony_ci			pin);
16062306a36Sopenharmony_ci		status = -EINVAL;
16162306a36Sopenharmony_ci		goto out_free_pin;
16262306a36Sopenharmony_ci	}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	/*
16562306a36Sopenharmony_ci	 * If there is no kind of request function for the pin we just assume
16662306a36Sopenharmony_ci	 * we got it by default and proceed.
16762306a36Sopenharmony_ci	 */
16862306a36Sopenharmony_ci	if (gpio_range && ops->gpio_request_enable)
16962306a36Sopenharmony_ci		/* This requests and enables a single GPIO pin */
17062306a36Sopenharmony_ci		status = ops->gpio_request_enable(pctldev, gpio_range, pin);
17162306a36Sopenharmony_ci	else if (ops->request)
17262306a36Sopenharmony_ci		status = ops->request(pctldev, pin);
17362306a36Sopenharmony_ci	else
17462306a36Sopenharmony_ci		status = 0;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (status) {
17762306a36Sopenharmony_ci		dev_err(pctldev->dev, "request() failed for pin %d\n", pin);
17862306a36Sopenharmony_ci		module_put(pctldev->owner);
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ciout_free_pin:
18262306a36Sopenharmony_ci	if (status) {
18362306a36Sopenharmony_ci		if (gpio_range) {
18462306a36Sopenharmony_ci			desc->gpio_owner = NULL;
18562306a36Sopenharmony_ci		} else {
18662306a36Sopenharmony_ci			desc->mux_usecount--;
18762306a36Sopenharmony_ci			if (!desc->mux_usecount)
18862306a36Sopenharmony_ci				desc->mux_owner = NULL;
18962306a36Sopenharmony_ci		}
19062306a36Sopenharmony_ci	}
19162306a36Sopenharmony_ciout:
19262306a36Sopenharmony_ci	if (status)
19362306a36Sopenharmony_ci		dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
19462306a36Sopenharmony_ci			pin, owner, status);
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	return status;
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci/**
20062306a36Sopenharmony_ci * pin_free() - release a single muxed in pin so something else can be muxed
20162306a36Sopenharmony_ci * @pctldev: pin controller device handling this pin
20262306a36Sopenharmony_ci * @pin: the pin to free
20362306a36Sopenharmony_ci * @gpio_range: the range matching the GPIO pin if this is a request for a
20462306a36Sopenharmony_ci *	single GPIO pin
20562306a36Sopenharmony_ci *
20662306a36Sopenharmony_ci * This function returns a pointer to the previous owner. This is used
20762306a36Sopenharmony_ci * for callers that dynamically allocate an owner name so it can be freed
20862306a36Sopenharmony_ci * once the pin is free. This is done for GPIO request functions.
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_cistatic const char *pin_free(struct pinctrl_dev *pctldev, int pin,
21162306a36Sopenharmony_ci			    struct pinctrl_gpio_range *gpio_range)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
21462306a36Sopenharmony_ci	struct pin_desc *desc;
21562306a36Sopenharmony_ci	const char *owner;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	desc = pin_desc_get(pctldev, pin);
21862306a36Sopenharmony_ci	if (desc == NULL) {
21962306a36Sopenharmony_ci		dev_err(pctldev->dev,
22062306a36Sopenharmony_ci			"pin is not registered so it cannot be freed\n");
22162306a36Sopenharmony_ci		return NULL;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	if (!gpio_range) {
22562306a36Sopenharmony_ci		/*
22662306a36Sopenharmony_ci		 * A pin should not be freed more times than allocated.
22762306a36Sopenharmony_ci		 */
22862306a36Sopenharmony_ci		if (WARN_ON(!desc->mux_usecount))
22962306a36Sopenharmony_ci			return NULL;
23062306a36Sopenharmony_ci		desc->mux_usecount--;
23162306a36Sopenharmony_ci		if (desc->mux_usecount)
23262306a36Sopenharmony_ci			return NULL;
23362306a36Sopenharmony_ci	}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	/*
23662306a36Sopenharmony_ci	 * If there is no kind of request function for the pin we just assume
23762306a36Sopenharmony_ci	 * we got it by default and proceed.
23862306a36Sopenharmony_ci	 */
23962306a36Sopenharmony_ci	if (gpio_range && ops->gpio_disable_free)
24062306a36Sopenharmony_ci		ops->gpio_disable_free(pctldev, gpio_range, pin);
24162306a36Sopenharmony_ci	else if (ops->free)
24262306a36Sopenharmony_ci		ops->free(pctldev, pin);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	if (gpio_range) {
24562306a36Sopenharmony_ci		owner = desc->gpio_owner;
24662306a36Sopenharmony_ci		desc->gpio_owner = NULL;
24762306a36Sopenharmony_ci	} else {
24862306a36Sopenharmony_ci		owner = desc->mux_owner;
24962306a36Sopenharmony_ci		desc->mux_owner = NULL;
25062306a36Sopenharmony_ci		desc->mux_setting = NULL;
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	module_put(pctldev->owner);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	return owner;
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci/**
25962306a36Sopenharmony_ci * pinmux_request_gpio() - request pinmuxing for a GPIO pin
26062306a36Sopenharmony_ci * @pctldev: pin controller device affected
26162306a36Sopenharmony_ci * @pin: the pin to mux in for GPIO
26262306a36Sopenharmony_ci * @range: the applicable GPIO range
26362306a36Sopenharmony_ci * @gpio: number of requested GPIO
26462306a36Sopenharmony_ci */
26562306a36Sopenharmony_ciint pinmux_request_gpio(struct pinctrl_dev *pctldev,
26662306a36Sopenharmony_ci			struct pinctrl_gpio_range *range,
26762306a36Sopenharmony_ci			unsigned pin, unsigned gpio)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	const char *owner;
27062306a36Sopenharmony_ci	int ret;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	/* Conjure some name stating what chip and pin this is taken by */
27362306a36Sopenharmony_ci	owner = kasprintf(GFP_KERNEL, "%s:%d", range->name, gpio);
27462306a36Sopenharmony_ci	if (!owner)
27562306a36Sopenharmony_ci		return -ENOMEM;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	ret = pin_request(pctldev, pin, owner, range);
27862306a36Sopenharmony_ci	if (ret < 0)
27962306a36Sopenharmony_ci		kfree(owner);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	return ret;
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci/**
28562306a36Sopenharmony_ci * pinmux_free_gpio() - release a pin from GPIO muxing
28662306a36Sopenharmony_ci * @pctldev: the pin controller device for the pin
28762306a36Sopenharmony_ci * @pin: the affected currently GPIO-muxed in pin
28862306a36Sopenharmony_ci * @range: applicable GPIO range
28962306a36Sopenharmony_ci */
29062306a36Sopenharmony_civoid pinmux_free_gpio(struct pinctrl_dev *pctldev, unsigned pin,
29162306a36Sopenharmony_ci		      struct pinctrl_gpio_range *range)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	const char *owner;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	owner = pin_free(pctldev, pin, range);
29662306a36Sopenharmony_ci	kfree(owner);
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci/**
30062306a36Sopenharmony_ci * pinmux_gpio_direction() - set the direction of a single muxed-in GPIO pin
30162306a36Sopenharmony_ci * @pctldev: the pin controller handling this pin
30262306a36Sopenharmony_ci * @range: applicable GPIO range
30362306a36Sopenharmony_ci * @pin: the affected GPIO pin in this controller
30462306a36Sopenharmony_ci * @input: true if we set the pin as input, false for output
30562306a36Sopenharmony_ci */
30662306a36Sopenharmony_ciint pinmux_gpio_direction(struct pinctrl_dev *pctldev,
30762306a36Sopenharmony_ci			  struct pinctrl_gpio_range *range,
30862306a36Sopenharmony_ci			  unsigned pin, bool input)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	const struct pinmux_ops *ops;
31162306a36Sopenharmony_ci	int ret;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	ops = pctldev->desc->pmxops;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	if (ops->gpio_set_direction)
31662306a36Sopenharmony_ci		ret = ops->gpio_set_direction(pctldev, range, pin, input);
31762306a36Sopenharmony_ci	else
31862306a36Sopenharmony_ci		ret = 0;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	return ret;
32162306a36Sopenharmony_ci}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_cistatic int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
32462306a36Sopenharmony_ci					const char *function)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
32762306a36Sopenharmony_ci	unsigned nfuncs = ops->get_functions_count(pctldev);
32862306a36Sopenharmony_ci	unsigned selector = 0;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	/* See if this pctldev has this function */
33162306a36Sopenharmony_ci	while (selector < nfuncs) {
33262306a36Sopenharmony_ci		const char *fname = ops->get_function_name(pctldev, selector);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci		if (!strcmp(function, fname))
33562306a36Sopenharmony_ci			return selector;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci		selector++;
33862306a36Sopenharmony_ci	}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	return -EINVAL;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ciint pinmux_map_to_setting(const struct pinctrl_map *map,
34462306a36Sopenharmony_ci			  struct pinctrl_setting *setting)
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	struct pinctrl_dev *pctldev = setting->pctldev;
34762306a36Sopenharmony_ci	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
34862306a36Sopenharmony_ci	char const * const *groups;
34962306a36Sopenharmony_ci	unsigned num_groups;
35062306a36Sopenharmony_ci	int ret;
35162306a36Sopenharmony_ci	const char *group;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	if (!pmxops) {
35462306a36Sopenharmony_ci		dev_err(pctldev->dev, "does not support mux function\n");
35562306a36Sopenharmony_ci		return -EINVAL;
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
35962306a36Sopenharmony_ci	if (ret < 0) {
36062306a36Sopenharmony_ci		dev_err(pctldev->dev, "invalid function %s in map table\n",
36162306a36Sopenharmony_ci			map->data.mux.function);
36262306a36Sopenharmony_ci		return ret;
36362306a36Sopenharmony_ci	}
36462306a36Sopenharmony_ci	setting->data.mux.func = ret;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
36762306a36Sopenharmony_ci					  &groups, &num_groups);
36862306a36Sopenharmony_ci	if (ret < 0) {
36962306a36Sopenharmony_ci		dev_err(pctldev->dev, "can't query groups for function %s\n",
37062306a36Sopenharmony_ci			map->data.mux.function);
37162306a36Sopenharmony_ci		return ret;
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci	if (!num_groups) {
37462306a36Sopenharmony_ci		dev_err(pctldev->dev,
37562306a36Sopenharmony_ci			"function %s can't be selected on any group\n",
37662306a36Sopenharmony_ci			map->data.mux.function);
37762306a36Sopenharmony_ci		return -EINVAL;
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci	if (map->data.mux.group) {
38062306a36Sopenharmony_ci		group = map->data.mux.group;
38162306a36Sopenharmony_ci		ret = match_string(groups, num_groups, group);
38262306a36Sopenharmony_ci		if (ret < 0) {
38362306a36Sopenharmony_ci			dev_err(pctldev->dev,
38462306a36Sopenharmony_ci				"invalid group \"%s\" for function \"%s\"\n",
38562306a36Sopenharmony_ci				group, map->data.mux.function);
38662306a36Sopenharmony_ci			return ret;
38762306a36Sopenharmony_ci		}
38862306a36Sopenharmony_ci	} else {
38962306a36Sopenharmony_ci		group = groups[0];
39062306a36Sopenharmony_ci	}
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	ret = pinctrl_get_group_selector(pctldev, group);
39362306a36Sopenharmony_ci	if (ret < 0) {
39462306a36Sopenharmony_ci		dev_err(pctldev->dev, "invalid group %s in map table\n",
39562306a36Sopenharmony_ci			map->data.mux.group);
39662306a36Sopenharmony_ci		return ret;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci	setting->data.mux.group = ret;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	return 0;
40162306a36Sopenharmony_ci}
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_civoid pinmux_free_setting(const struct pinctrl_setting *setting)
40462306a36Sopenharmony_ci{
40562306a36Sopenharmony_ci	/* This function is currently unused */
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ciint pinmux_enable_setting(const struct pinctrl_setting *setting)
40962306a36Sopenharmony_ci{
41062306a36Sopenharmony_ci	struct pinctrl_dev *pctldev = setting->pctldev;
41162306a36Sopenharmony_ci	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
41262306a36Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
41362306a36Sopenharmony_ci	int ret = 0;
41462306a36Sopenharmony_ci	const unsigned *pins = NULL;
41562306a36Sopenharmony_ci	unsigned num_pins = 0;
41662306a36Sopenharmony_ci	int i;
41762306a36Sopenharmony_ci	struct pin_desc *desc;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	if (pctlops->get_group_pins)
42062306a36Sopenharmony_ci		ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
42162306a36Sopenharmony_ci					      &pins, &num_pins);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	if (ret) {
42462306a36Sopenharmony_ci		const char *gname;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci		/* errors only affect debug data, so just warn */
42762306a36Sopenharmony_ci		gname = pctlops->get_group_name(pctldev,
42862306a36Sopenharmony_ci						setting->data.mux.group);
42962306a36Sopenharmony_ci		dev_warn(pctldev->dev,
43062306a36Sopenharmony_ci			 "could not get pins for group %s\n",
43162306a36Sopenharmony_ci			 gname);
43262306a36Sopenharmony_ci		num_pins = 0;
43362306a36Sopenharmony_ci	}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	/* Try to allocate all pins in this group, one by one */
43662306a36Sopenharmony_ci	for (i = 0; i < num_pins; i++) {
43762306a36Sopenharmony_ci		ret = pin_request(pctldev, pins[i], setting->dev_name, NULL);
43862306a36Sopenharmony_ci		if (ret) {
43962306a36Sopenharmony_ci			const char *gname;
44062306a36Sopenharmony_ci			const char *pname;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci			desc = pin_desc_get(pctldev, pins[i]);
44362306a36Sopenharmony_ci			pname = desc ? desc->name : "non-existing";
44462306a36Sopenharmony_ci			gname = pctlops->get_group_name(pctldev,
44562306a36Sopenharmony_ci						setting->data.mux.group);
44662306a36Sopenharmony_ci			dev_err(pctldev->dev,
44762306a36Sopenharmony_ci				"could not request pin %d (%s) from group %s "
44862306a36Sopenharmony_ci				" on device %s\n",
44962306a36Sopenharmony_ci				pins[i], pname, gname,
45062306a36Sopenharmony_ci				pinctrl_dev_get_name(pctldev));
45162306a36Sopenharmony_ci			goto err_pin_request;
45262306a36Sopenharmony_ci		}
45362306a36Sopenharmony_ci	}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	/* Now that we have acquired the pins, encode the mux setting */
45662306a36Sopenharmony_ci	for (i = 0; i < num_pins; i++) {
45762306a36Sopenharmony_ci		desc = pin_desc_get(pctldev, pins[i]);
45862306a36Sopenharmony_ci		if (desc == NULL) {
45962306a36Sopenharmony_ci			dev_warn(pctldev->dev,
46062306a36Sopenharmony_ci				 "could not get pin desc for pin %d\n",
46162306a36Sopenharmony_ci				 pins[i]);
46262306a36Sopenharmony_ci			continue;
46362306a36Sopenharmony_ci		}
46462306a36Sopenharmony_ci		desc->mux_setting = &(setting->data.mux);
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	ret = ops->set_mux(pctldev, setting->data.mux.func,
46862306a36Sopenharmony_ci			   setting->data.mux.group);
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	if (ret)
47162306a36Sopenharmony_ci		goto err_set_mux;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	return 0;
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_cierr_set_mux:
47662306a36Sopenharmony_ci	for (i = 0; i < num_pins; i++) {
47762306a36Sopenharmony_ci		desc = pin_desc_get(pctldev, pins[i]);
47862306a36Sopenharmony_ci		if (desc)
47962306a36Sopenharmony_ci			desc->mux_setting = NULL;
48062306a36Sopenharmony_ci	}
48162306a36Sopenharmony_cierr_pin_request:
48262306a36Sopenharmony_ci	/* On error release all taken pins */
48362306a36Sopenharmony_ci	while (--i >= 0)
48462306a36Sopenharmony_ci		pin_free(pctldev, pins[i], NULL);
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	return ret;
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_civoid pinmux_disable_setting(const struct pinctrl_setting *setting)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	struct pinctrl_dev *pctldev = setting->pctldev;
49262306a36Sopenharmony_ci	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
49362306a36Sopenharmony_ci	int ret = 0;
49462306a36Sopenharmony_ci	const unsigned *pins = NULL;
49562306a36Sopenharmony_ci	unsigned num_pins = 0;
49662306a36Sopenharmony_ci	int i;
49762306a36Sopenharmony_ci	struct pin_desc *desc;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	if (pctlops->get_group_pins)
50062306a36Sopenharmony_ci		ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
50162306a36Sopenharmony_ci					      &pins, &num_pins);
50262306a36Sopenharmony_ci	if (ret) {
50362306a36Sopenharmony_ci		const char *gname;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci		/* errors only affect debug data, so just warn */
50662306a36Sopenharmony_ci		gname = pctlops->get_group_name(pctldev,
50762306a36Sopenharmony_ci						setting->data.mux.group);
50862306a36Sopenharmony_ci		dev_warn(pctldev->dev,
50962306a36Sopenharmony_ci			 "could not get pins for group %s\n",
51062306a36Sopenharmony_ci			 gname);
51162306a36Sopenharmony_ci		num_pins = 0;
51262306a36Sopenharmony_ci	}
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	/* Flag the descs that no setting is active */
51562306a36Sopenharmony_ci	for (i = 0; i < num_pins; i++) {
51662306a36Sopenharmony_ci		desc = pin_desc_get(pctldev, pins[i]);
51762306a36Sopenharmony_ci		if (desc == NULL) {
51862306a36Sopenharmony_ci			dev_warn(pctldev->dev,
51962306a36Sopenharmony_ci				 "could not get pin desc for pin %d\n",
52062306a36Sopenharmony_ci				 pins[i]);
52162306a36Sopenharmony_ci			continue;
52262306a36Sopenharmony_ci		}
52362306a36Sopenharmony_ci		if (desc->mux_setting == &(setting->data.mux)) {
52462306a36Sopenharmony_ci			pin_free(pctldev, pins[i], NULL);
52562306a36Sopenharmony_ci		} else {
52662306a36Sopenharmony_ci			const char *gname;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci			gname = pctlops->get_group_name(pctldev,
52962306a36Sopenharmony_ci						setting->data.mux.group);
53062306a36Sopenharmony_ci			dev_warn(pctldev->dev,
53162306a36Sopenharmony_ci				 "not freeing pin %d (%s) as part of "
53262306a36Sopenharmony_ci				 "deactivating group %s - it is already "
53362306a36Sopenharmony_ci				 "used for some other setting",
53462306a36Sopenharmony_ci				 pins[i], desc->name, gname);
53562306a36Sopenharmony_ci		}
53662306a36Sopenharmony_ci	}
53762306a36Sopenharmony_ci}
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci/* Called from pincontrol core */
54262306a36Sopenharmony_cistatic int pinmux_functions_show(struct seq_file *s, void *what)
54362306a36Sopenharmony_ci{
54462306a36Sopenharmony_ci	struct pinctrl_dev *pctldev = s->private;
54562306a36Sopenharmony_ci	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
54662306a36Sopenharmony_ci	unsigned nfuncs;
54762306a36Sopenharmony_ci	unsigned func_selector = 0;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	if (!pmxops)
55062306a36Sopenharmony_ci		return 0;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	mutex_lock(&pctldev->mutex);
55362306a36Sopenharmony_ci	nfuncs = pmxops->get_functions_count(pctldev);
55462306a36Sopenharmony_ci	while (func_selector < nfuncs) {
55562306a36Sopenharmony_ci		const char *func = pmxops->get_function_name(pctldev,
55662306a36Sopenharmony_ci							  func_selector);
55762306a36Sopenharmony_ci		const char * const *groups;
55862306a36Sopenharmony_ci		unsigned num_groups;
55962306a36Sopenharmony_ci		int ret;
56062306a36Sopenharmony_ci		int i;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci		ret = pmxops->get_function_groups(pctldev, func_selector,
56362306a36Sopenharmony_ci						  &groups, &num_groups);
56462306a36Sopenharmony_ci		if (ret) {
56562306a36Sopenharmony_ci			seq_printf(s, "function %s: COULD NOT GET GROUPS\n",
56662306a36Sopenharmony_ci				   func);
56762306a36Sopenharmony_ci			func_selector++;
56862306a36Sopenharmony_ci			continue;
56962306a36Sopenharmony_ci		}
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci		seq_printf(s, "function %d: %s, groups = [ ", func_selector, func);
57262306a36Sopenharmony_ci		for (i = 0; i < num_groups; i++)
57362306a36Sopenharmony_ci			seq_printf(s, "%s ", groups[i]);
57462306a36Sopenharmony_ci		seq_puts(s, "]\n");
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci		func_selector++;
57762306a36Sopenharmony_ci	}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	mutex_unlock(&pctldev->mutex);
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	return 0;
58262306a36Sopenharmony_ci}
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_cistatic int pinmux_pins_show(struct seq_file *s, void *what)
58562306a36Sopenharmony_ci{
58662306a36Sopenharmony_ci	struct pinctrl_dev *pctldev = s->private;
58762306a36Sopenharmony_ci	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
58862306a36Sopenharmony_ci	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
58962306a36Sopenharmony_ci	unsigned i, pin;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	if (!pmxops)
59262306a36Sopenharmony_ci		return 0;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	seq_puts(s, "Pinmux settings per pin\n");
59562306a36Sopenharmony_ci	if (pmxops->strict)
59662306a36Sopenharmony_ci		seq_puts(s,
59762306a36Sopenharmony_ci		 "Format: pin (name): mux_owner|gpio_owner (strict) hog?\n");
59862306a36Sopenharmony_ci	else
59962306a36Sopenharmony_ci		seq_puts(s,
60062306a36Sopenharmony_ci		"Format: pin (name): mux_owner gpio_owner hog?\n");
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	mutex_lock(&pctldev->mutex);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	/* The pin number can be retrived from the pin controller descriptor */
60562306a36Sopenharmony_ci	for (i = 0; i < pctldev->desc->npins; i++) {
60662306a36Sopenharmony_ci		struct pin_desc *desc;
60762306a36Sopenharmony_ci		bool is_hog = false;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci		pin = pctldev->desc->pins[i].number;
61062306a36Sopenharmony_ci		desc = pin_desc_get(pctldev, pin);
61162306a36Sopenharmony_ci		/* Skip if we cannot search the pin */
61262306a36Sopenharmony_ci		if (desc == NULL)
61362306a36Sopenharmony_ci			continue;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci		if (desc->mux_owner &&
61662306a36Sopenharmony_ci		    !strcmp(desc->mux_owner, pinctrl_dev_get_name(pctldev)))
61762306a36Sopenharmony_ci			is_hog = true;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci		if (pmxops->strict) {
62062306a36Sopenharmony_ci			if (desc->mux_owner)
62162306a36Sopenharmony_ci				seq_printf(s, "pin %d (%s): device %s%s",
62262306a36Sopenharmony_ci					   pin, desc->name, desc->mux_owner,
62362306a36Sopenharmony_ci					   is_hog ? " (HOG)" : "");
62462306a36Sopenharmony_ci			else if (desc->gpio_owner)
62562306a36Sopenharmony_ci				seq_printf(s, "pin %d (%s): GPIO %s",
62662306a36Sopenharmony_ci					   pin, desc->name, desc->gpio_owner);
62762306a36Sopenharmony_ci			else
62862306a36Sopenharmony_ci				seq_printf(s, "pin %d (%s): UNCLAIMED",
62962306a36Sopenharmony_ci					   pin, desc->name);
63062306a36Sopenharmony_ci		} else {
63162306a36Sopenharmony_ci			/* For non-strict controllers */
63262306a36Sopenharmony_ci			seq_printf(s, "pin %d (%s): %s %s%s", pin, desc->name,
63362306a36Sopenharmony_ci				   desc->mux_owner ? desc->mux_owner
63462306a36Sopenharmony_ci				   : "(MUX UNCLAIMED)",
63562306a36Sopenharmony_ci				   desc->gpio_owner ? desc->gpio_owner
63662306a36Sopenharmony_ci				   : "(GPIO UNCLAIMED)",
63762306a36Sopenharmony_ci				   is_hog ? " (HOG)" : "");
63862306a36Sopenharmony_ci		}
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		/* If mux: print function+group claiming the pin */
64162306a36Sopenharmony_ci		if (desc->mux_setting)
64262306a36Sopenharmony_ci			seq_printf(s, " function %s group %s\n",
64362306a36Sopenharmony_ci				   pmxops->get_function_name(pctldev,
64462306a36Sopenharmony_ci					desc->mux_setting->func),
64562306a36Sopenharmony_ci				   pctlops->get_group_name(pctldev,
64662306a36Sopenharmony_ci					desc->mux_setting->group));
64762306a36Sopenharmony_ci		else
64862306a36Sopenharmony_ci			seq_putc(s, '\n');
64962306a36Sopenharmony_ci	}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	mutex_unlock(&pctldev->mutex);
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	return 0;
65462306a36Sopenharmony_ci}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_civoid pinmux_show_map(struct seq_file *s, const struct pinctrl_map *map)
65762306a36Sopenharmony_ci{
65862306a36Sopenharmony_ci	seq_printf(s, "group %s\nfunction %s\n",
65962306a36Sopenharmony_ci		map->data.mux.group ? map->data.mux.group : "(default)",
66062306a36Sopenharmony_ci		map->data.mux.function);
66162306a36Sopenharmony_ci}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_civoid pinmux_show_setting(struct seq_file *s,
66462306a36Sopenharmony_ci			 const struct pinctrl_setting *setting)
66562306a36Sopenharmony_ci{
66662306a36Sopenharmony_ci	struct pinctrl_dev *pctldev = setting->pctldev;
66762306a36Sopenharmony_ci	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
66862306a36Sopenharmony_ci	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	seq_printf(s, "group: %s (%u) function: %s (%u)\n",
67162306a36Sopenharmony_ci		   pctlops->get_group_name(pctldev, setting->data.mux.group),
67262306a36Sopenharmony_ci		   setting->data.mux.group,
67362306a36Sopenharmony_ci		   pmxops->get_function_name(pctldev, setting->data.mux.func),
67462306a36Sopenharmony_ci		   setting->data.mux.func);
67562306a36Sopenharmony_ci}
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(pinmux_functions);
67862306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(pinmux_pins);
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_cistatic ssize_t pinmux_select(struct file *file, const char __user *user_buf,
68162306a36Sopenharmony_ci				   size_t len, loff_t *ppos)
68262306a36Sopenharmony_ci{
68362306a36Sopenharmony_ci	struct seq_file *sfile = file->private_data;
68462306a36Sopenharmony_ci	struct pinctrl_dev *pctldev = sfile->private;
68562306a36Sopenharmony_ci	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
68662306a36Sopenharmony_ci	const char *const *groups;
68762306a36Sopenharmony_ci	char *buf, *gname, *fname;
68862306a36Sopenharmony_ci	unsigned int num_groups;
68962306a36Sopenharmony_ci	int fsel, gsel, ret;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	buf = memdup_user_nul(user_buf, len);
69262306a36Sopenharmony_ci	if (IS_ERR(buf))
69362306a36Sopenharmony_ci		return PTR_ERR(buf);
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	/* remove leading and trailing spaces of input buffer */
69662306a36Sopenharmony_ci	gname = strstrip(buf);
69762306a36Sopenharmony_ci	if (*gname == '\0') {
69862306a36Sopenharmony_ci		ret = -EINVAL;
69962306a36Sopenharmony_ci		goto exit_free_buf;
70062306a36Sopenharmony_ci	}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	/* find a separator which is a spacelike character */
70362306a36Sopenharmony_ci	for (fname = gname; !isspace(*fname); fname++) {
70462306a36Sopenharmony_ci		if (*fname == '\0') {
70562306a36Sopenharmony_ci			ret = -EINVAL;
70662306a36Sopenharmony_ci			goto exit_free_buf;
70762306a36Sopenharmony_ci		}
70862306a36Sopenharmony_ci	}
70962306a36Sopenharmony_ci	*fname = '\0';
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	/* drop extra spaces between function and group names */
71262306a36Sopenharmony_ci	fname = skip_spaces(fname + 1);
71362306a36Sopenharmony_ci	if (*fname == '\0') {
71462306a36Sopenharmony_ci		ret = -EINVAL;
71562306a36Sopenharmony_ci		goto exit_free_buf;
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	ret = pinmux_func_name_to_selector(pctldev, fname);
71962306a36Sopenharmony_ci	if (ret < 0) {
72062306a36Sopenharmony_ci		dev_err(pctldev->dev, "invalid function %s in map table\n", fname);
72162306a36Sopenharmony_ci		goto exit_free_buf;
72262306a36Sopenharmony_ci	}
72362306a36Sopenharmony_ci	fsel = ret;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	ret = pmxops->get_function_groups(pctldev, fsel, &groups, &num_groups);
72662306a36Sopenharmony_ci	if (ret) {
72762306a36Sopenharmony_ci		dev_err(pctldev->dev, "no groups for function %d (%s)", fsel, fname);
72862306a36Sopenharmony_ci		goto exit_free_buf;
72962306a36Sopenharmony_ci	}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	ret = match_string(groups, num_groups, gname);
73262306a36Sopenharmony_ci	if (ret < 0) {
73362306a36Sopenharmony_ci		dev_err(pctldev->dev, "invalid group %s", gname);
73462306a36Sopenharmony_ci		goto exit_free_buf;
73562306a36Sopenharmony_ci	}
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	ret = pinctrl_get_group_selector(pctldev, gname);
73862306a36Sopenharmony_ci	if (ret < 0)
73962306a36Sopenharmony_ci		goto exit_free_buf;
74062306a36Sopenharmony_ci	gsel = ret;
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	ret = pmxops->set_mux(pctldev, fsel, gsel);
74362306a36Sopenharmony_ci	if (ret) {
74462306a36Sopenharmony_ci		dev_err(pctldev->dev, "set_mux() failed: %d", ret);
74562306a36Sopenharmony_ci		goto exit_free_buf;
74662306a36Sopenharmony_ci	}
74762306a36Sopenharmony_ci	ret = len;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ciexit_free_buf:
75062306a36Sopenharmony_ci	kfree(buf);
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	return ret;
75362306a36Sopenharmony_ci}
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_cistatic int pinmux_select_open(struct inode *inode, struct file *file)
75662306a36Sopenharmony_ci{
75762306a36Sopenharmony_ci	return single_open(file, NULL, inode->i_private);
75862306a36Sopenharmony_ci}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_cistatic const struct file_operations pinmux_select_ops = {
76162306a36Sopenharmony_ci	.owner = THIS_MODULE,
76262306a36Sopenharmony_ci	.open = pinmux_select_open,
76362306a36Sopenharmony_ci	.write = pinmux_select,
76462306a36Sopenharmony_ci	.llseek = no_llseek,
76562306a36Sopenharmony_ci	.release = single_release,
76662306a36Sopenharmony_ci};
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_civoid pinmux_init_device_debugfs(struct dentry *devroot,
76962306a36Sopenharmony_ci			 struct pinctrl_dev *pctldev)
77062306a36Sopenharmony_ci{
77162306a36Sopenharmony_ci	debugfs_create_file("pinmux-functions", 0444,
77262306a36Sopenharmony_ci			    devroot, pctldev, &pinmux_functions_fops);
77362306a36Sopenharmony_ci	debugfs_create_file("pinmux-pins", 0444,
77462306a36Sopenharmony_ci			    devroot, pctldev, &pinmux_pins_fops);
77562306a36Sopenharmony_ci	debugfs_create_file("pinmux-select", 0200,
77662306a36Sopenharmony_ci			    devroot, pctldev, &pinmux_select_ops);
77762306a36Sopenharmony_ci}
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci#ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci/**
78462306a36Sopenharmony_ci * pinmux_generic_get_function_count() - returns number of functions
78562306a36Sopenharmony_ci * @pctldev: pin controller device
78662306a36Sopenharmony_ci */
78762306a36Sopenharmony_ciint pinmux_generic_get_function_count(struct pinctrl_dev *pctldev)
78862306a36Sopenharmony_ci{
78962306a36Sopenharmony_ci	return pctldev->num_functions;
79062306a36Sopenharmony_ci}
79162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_get_function_count);
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci/**
79462306a36Sopenharmony_ci * pinmux_generic_get_function_name() - returns the function name
79562306a36Sopenharmony_ci * @pctldev: pin controller device
79662306a36Sopenharmony_ci * @selector: function number
79762306a36Sopenharmony_ci */
79862306a36Sopenharmony_ciconst char *
79962306a36Sopenharmony_cipinmux_generic_get_function_name(struct pinctrl_dev *pctldev,
80062306a36Sopenharmony_ci				 unsigned int selector)
80162306a36Sopenharmony_ci{
80262306a36Sopenharmony_ci	struct function_desc *function;
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	function = radix_tree_lookup(&pctldev->pin_function_tree,
80562306a36Sopenharmony_ci				     selector);
80662306a36Sopenharmony_ci	if (!function)
80762306a36Sopenharmony_ci		return NULL;
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	return function->name;
81062306a36Sopenharmony_ci}
81162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_get_function_name);
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci/**
81462306a36Sopenharmony_ci * pinmux_generic_get_function_groups() - gets the function groups
81562306a36Sopenharmony_ci * @pctldev: pin controller device
81662306a36Sopenharmony_ci * @selector: function number
81762306a36Sopenharmony_ci * @groups: array of pin groups
81862306a36Sopenharmony_ci * @num_groups: number of pin groups
81962306a36Sopenharmony_ci */
82062306a36Sopenharmony_ciint pinmux_generic_get_function_groups(struct pinctrl_dev *pctldev,
82162306a36Sopenharmony_ci				       unsigned int selector,
82262306a36Sopenharmony_ci				       const char * const **groups,
82362306a36Sopenharmony_ci				       unsigned * const num_groups)
82462306a36Sopenharmony_ci{
82562306a36Sopenharmony_ci	struct function_desc *function;
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	function = radix_tree_lookup(&pctldev->pin_function_tree,
82862306a36Sopenharmony_ci				     selector);
82962306a36Sopenharmony_ci	if (!function) {
83062306a36Sopenharmony_ci		dev_err(pctldev->dev, "%s could not find function%i\n",
83162306a36Sopenharmony_ci			__func__, selector);
83262306a36Sopenharmony_ci		return -EINVAL;
83362306a36Sopenharmony_ci	}
83462306a36Sopenharmony_ci	*groups = function->group_names;
83562306a36Sopenharmony_ci	*num_groups = function->num_group_names;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	return 0;
83862306a36Sopenharmony_ci}
83962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_get_function_groups);
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci/**
84262306a36Sopenharmony_ci * pinmux_generic_get_function() - returns a function based on the number
84362306a36Sopenharmony_ci * @pctldev: pin controller device
84462306a36Sopenharmony_ci * @selector: function number
84562306a36Sopenharmony_ci */
84662306a36Sopenharmony_cistruct function_desc *pinmux_generic_get_function(struct pinctrl_dev *pctldev,
84762306a36Sopenharmony_ci						  unsigned int selector)
84862306a36Sopenharmony_ci{
84962306a36Sopenharmony_ci	struct function_desc *function;
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	function = radix_tree_lookup(&pctldev->pin_function_tree,
85262306a36Sopenharmony_ci				     selector);
85362306a36Sopenharmony_ci	if (!function)
85462306a36Sopenharmony_ci		return NULL;
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	return function;
85762306a36Sopenharmony_ci}
85862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_get_function);
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci/**
86162306a36Sopenharmony_ci * pinmux_generic_add_function() - adds a function group
86262306a36Sopenharmony_ci * @pctldev: pin controller device
86362306a36Sopenharmony_ci * @name: name of the function
86462306a36Sopenharmony_ci * @groups: array of pin groups
86562306a36Sopenharmony_ci * @num_groups: number of pin groups
86662306a36Sopenharmony_ci * @data: pin controller driver specific data
86762306a36Sopenharmony_ci */
86862306a36Sopenharmony_ciint pinmux_generic_add_function(struct pinctrl_dev *pctldev,
86962306a36Sopenharmony_ci				const char *name,
87062306a36Sopenharmony_ci				const char * const *groups,
87162306a36Sopenharmony_ci				const unsigned int num_groups,
87262306a36Sopenharmony_ci				void *data)
87362306a36Sopenharmony_ci{
87462306a36Sopenharmony_ci	struct function_desc *function;
87562306a36Sopenharmony_ci	int selector, error;
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	if (!name)
87862306a36Sopenharmony_ci		return -EINVAL;
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	selector = pinmux_func_name_to_selector(pctldev, name);
88162306a36Sopenharmony_ci	if (selector >= 0)
88262306a36Sopenharmony_ci		return selector;
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	selector = pctldev->num_functions;
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	function = devm_kzalloc(pctldev->dev, sizeof(*function), GFP_KERNEL);
88762306a36Sopenharmony_ci	if (!function)
88862306a36Sopenharmony_ci		return -ENOMEM;
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	function->name = name;
89162306a36Sopenharmony_ci	function->group_names = groups;
89262306a36Sopenharmony_ci	function->num_group_names = num_groups;
89362306a36Sopenharmony_ci	function->data = data;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	error = radix_tree_insert(&pctldev->pin_function_tree, selector, function);
89662306a36Sopenharmony_ci	if (error)
89762306a36Sopenharmony_ci		return error;
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci	pctldev->num_functions++;
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	return selector;
90262306a36Sopenharmony_ci}
90362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_add_function);
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci/**
90662306a36Sopenharmony_ci * pinmux_generic_remove_function() - removes a numbered function
90762306a36Sopenharmony_ci * @pctldev: pin controller device
90862306a36Sopenharmony_ci * @selector: function number
90962306a36Sopenharmony_ci *
91062306a36Sopenharmony_ci * Note that the caller must take care of locking.
91162306a36Sopenharmony_ci */
91262306a36Sopenharmony_ciint pinmux_generic_remove_function(struct pinctrl_dev *pctldev,
91362306a36Sopenharmony_ci				   unsigned int selector)
91462306a36Sopenharmony_ci{
91562306a36Sopenharmony_ci	struct function_desc *function;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	function = radix_tree_lookup(&pctldev->pin_function_tree,
91862306a36Sopenharmony_ci				     selector);
91962306a36Sopenharmony_ci	if (!function)
92062306a36Sopenharmony_ci		return -ENOENT;
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	radix_tree_delete(&pctldev->pin_function_tree, selector);
92362306a36Sopenharmony_ci	devm_kfree(pctldev->dev, function);
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	pctldev->num_functions--;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	return 0;
92862306a36Sopenharmony_ci}
92962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_remove_function);
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci/**
93262306a36Sopenharmony_ci * pinmux_generic_free_functions() - removes all functions
93362306a36Sopenharmony_ci * @pctldev: pin controller device
93462306a36Sopenharmony_ci *
93562306a36Sopenharmony_ci * Note that the caller must take care of locking. The pinctrl
93662306a36Sopenharmony_ci * functions are allocated with devm_kzalloc() so no need to free
93762306a36Sopenharmony_ci * them here.
93862306a36Sopenharmony_ci */
93962306a36Sopenharmony_civoid pinmux_generic_free_functions(struct pinctrl_dev *pctldev)
94062306a36Sopenharmony_ci{
94162306a36Sopenharmony_ci	struct radix_tree_iter iter;
94262306a36Sopenharmony_ci	void __rcu **slot;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	radix_tree_for_each_slot(slot, &pctldev->pin_function_tree, &iter, 0)
94562306a36Sopenharmony_ci		radix_tree_delete(&pctldev->pin_function_tree, iter.index);
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	pctldev->num_functions = 0;
94862306a36Sopenharmony_ci}
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci#endif /* CONFIG_GENERIC_PINMUX_FUNCTIONS */
951