18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Core driver for the pin muxing portions of the pin control subsystem
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2011-2012 ST-Ericsson SA
68c2ecf20Sopenharmony_ci * Written on behalf of Linaro for ST-Ericsson
78c2ecf20Sopenharmony_ci * Based on bits of regulator core, gpio core and clk core
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Author: Linus Walleij <linus.walleij@linaro.org>
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "pinmux core: " fmt
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <linux/kernel.h>
168c2ecf20Sopenharmony_ci#include <linux/module.h>
178c2ecf20Sopenharmony_ci#include <linux/init.h>
188c2ecf20Sopenharmony_ci#include <linux/device.h>
198c2ecf20Sopenharmony_ci#include <linux/slab.h>
208c2ecf20Sopenharmony_ci#include <linux/radix-tree.h>
218c2ecf20Sopenharmony_ci#include <linux/err.h>
228c2ecf20Sopenharmony_ci#include <linux/list.h>
238c2ecf20Sopenharmony_ci#include <linux/string.h>
248c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
258c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
268c2ecf20Sopenharmony_ci#include <linux/pinctrl/machine.h>
278c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinmux.h>
288c2ecf20Sopenharmony_ci#include "core.h"
298c2ecf20Sopenharmony_ci#include "pinmux.h"
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ciint pinmux_check_ops(struct pinctrl_dev *pctldev)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
348c2ecf20Sopenharmony_ci	unsigned nfuncs;
358c2ecf20Sopenharmony_ci	unsigned selector = 0;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	/* Check that we implement required operations */
388c2ecf20Sopenharmony_ci	if (!ops ||
398c2ecf20Sopenharmony_ci	    !ops->get_functions_count ||
408c2ecf20Sopenharmony_ci	    !ops->get_function_name ||
418c2ecf20Sopenharmony_ci	    !ops->get_function_groups ||
428c2ecf20Sopenharmony_ci	    !ops->set_mux) {
438c2ecf20Sopenharmony_ci		dev_err(pctldev->dev, "pinmux ops lacks necessary functions\n");
448c2ecf20Sopenharmony_ci		return -EINVAL;
458c2ecf20Sopenharmony_ci	}
468c2ecf20Sopenharmony_ci	/* Check that all functions registered have names */
478c2ecf20Sopenharmony_ci	nfuncs = ops->get_functions_count(pctldev);
488c2ecf20Sopenharmony_ci	while (selector < nfuncs) {
498c2ecf20Sopenharmony_ci		const char *fname = ops->get_function_name(pctldev,
508c2ecf20Sopenharmony_ci							   selector);
518c2ecf20Sopenharmony_ci		if (!fname) {
528c2ecf20Sopenharmony_ci			dev_err(pctldev->dev, "pinmux ops has no name for function%u\n",
538c2ecf20Sopenharmony_ci				selector);
548c2ecf20Sopenharmony_ci			return -EINVAL;
558c2ecf20Sopenharmony_ci		}
568c2ecf20Sopenharmony_ci		selector++;
578c2ecf20Sopenharmony_ci	}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	return 0;
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ciint pinmux_validate_map(const struct pinctrl_map *map, int i)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	if (!map->data.mux.function) {
658c2ecf20Sopenharmony_ci		pr_err("failed to register map %s (%d): no function given\n",
668c2ecf20Sopenharmony_ci		       map->name, i);
678c2ecf20Sopenharmony_ci		return -EINVAL;
688c2ecf20Sopenharmony_ci	}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	return 0;
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/**
748c2ecf20Sopenharmony_ci * pinmux_can_be_used_for_gpio() - check if a specific pin
758c2ecf20Sopenharmony_ci *	is either muxed to a different function or used as gpio.
768c2ecf20Sopenharmony_ci *
778c2ecf20Sopenharmony_ci * @pctldev: the associated pin controller device
788c2ecf20Sopenharmony_ci * @pin: the pin number in the global pin space
798c2ecf20Sopenharmony_ci *
808c2ecf20Sopenharmony_ci * Controllers not defined as strict will always return true,
818c2ecf20Sopenharmony_ci * menaning that the gpio can be used.
828c2ecf20Sopenharmony_ci */
838c2ecf20Sopenharmony_cibool pinmux_can_be_used_for_gpio(struct pinctrl_dev *pctldev, unsigned pin)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	struct pin_desc *desc = pin_desc_get(pctldev, pin);
868c2ecf20Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	/* Can't inspect pin, assume it can be used */
898c2ecf20Sopenharmony_ci	if (!desc || !ops)
908c2ecf20Sopenharmony_ci		return true;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	if (ops->strict && desc->mux_usecount)
938c2ecf20Sopenharmony_ci		return false;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	return !(ops->strict && !!desc->gpio_owner);
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci/**
998c2ecf20Sopenharmony_ci * pin_request() - request a single pin to be muxed in, typically for GPIO
1008c2ecf20Sopenharmony_ci * @pctldev: the associated pin controller device
1018c2ecf20Sopenharmony_ci * @pin: the pin number in the global pin space
1028c2ecf20Sopenharmony_ci * @owner: a representation of the owner of this pin; typically the device
1038c2ecf20Sopenharmony_ci *	name that controls its mux function, or the requested GPIO name
1048c2ecf20Sopenharmony_ci * @gpio_range: the range matching the GPIO pin if this is a request for a
1058c2ecf20Sopenharmony_ci *	single GPIO pin
1068c2ecf20Sopenharmony_ci */
1078c2ecf20Sopenharmony_cistatic int pin_request(struct pinctrl_dev *pctldev,
1088c2ecf20Sopenharmony_ci		       int pin, const char *owner,
1098c2ecf20Sopenharmony_ci		       struct pinctrl_gpio_range *gpio_range)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	struct pin_desc *desc;
1128c2ecf20Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
1138c2ecf20Sopenharmony_ci	int status = -EINVAL;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	desc = pin_desc_get(pctldev, pin);
1168c2ecf20Sopenharmony_ci	if (desc == NULL) {
1178c2ecf20Sopenharmony_ci		dev_err(pctldev->dev,
1188c2ecf20Sopenharmony_ci			"pin %d is not registered so it cannot be requested\n",
1198c2ecf20Sopenharmony_ci			pin);
1208c2ecf20Sopenharmony_ci		goto out;
1218c2ecf20Sopenharmony_ci	}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
1248c2ecf20Sopenharmony_ci		pin, desc->name, owner);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	if ((!gpio_range || ops->strict) &&
1278c2ecf20Sopenharmony_ci	    desc->mux_usecount && strcmp(desc->mux_owner, owner)) {
1288c2ecf20Sopenharmony_ci		dev_err(pctldev->dev,
1298c2ecf20Sopenharmony_ci			"pin %s already requested by %s; cannot claim for %s\n",
1308c2ecf20Sopenharmony_ci			desc->name, desc->mux_owner, owner);
1318c2ecf20Sopenharmony_ci		goto out;
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	if ((gpio_range || ops->strict) && desc->gpio_owner) {
1358c2ecf20Sopenharmony_ci		dev_err(pctldev->dev,
1368c2ecf20Sopenharmony_ci			"pin %s already requested by %s; cannot claim for %s\n",
1378c2ecf20Sopenharmony_ci			desc->name, desc->gpio_owner, owner);
1388c2ecf20Sopenharmony_ci		goto out;
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	if (gpio_range) {
1428c2ecf20Sopenharmony_ci		desc->gpio_owner = owner;
1438c2ecf20Sopenharmony_ci	} else {
1448c2ecf20Sopenharmony_ci		desc->mux_usecount++;
1458c2ecf20Sopenharmony_ci		if (desc->mux_usecount > 1)
1468c2ecf20Sopenharmony_ci			return 0;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci		desc->mux_owner = owner;
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	/* Let each pin increase references to this module */
1528c2ecf20Sopenharmony_ci	if (!try_module_get(pctldev->owner)) {
1538c2ecf20Sopenharmony_ci		dev_err(pctldev->dev,
1548c2ecf20Sopenharmony_ci			"could not increase module refcount for pin %d\n",
1558c2ecf20Sopenharmony_ci			pin);
1568c2ecf20Sopenharmony_ci		status = -EINVAL;
1578c2ecf20Sopenharmony_ci		goto out_free_pin;
1588c2ecf20Sopenharmony_ci	}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	/*
1618c2ecf20Sopenharmony_ci	 * If there is no kind of request function for the pin we just assume
1628c2ecf20Sopenharmony_ci	 * we got it by default and proceed.
1638c2ecf20Sopenharmony_ci	 */
1648c2ecf20Sopenharmony_ci	if (gpio_range && ops->gpio_request_enable)
1658c2ecf20Sopenharmony_ci		/* This requests and enables a single GPIO pin */
1668c2ecf20Sopenharmony_ci		status = ops->gpio_request_enable(pctldev, gpio_range, pin);
1678c2ecf20Sopenharmony_ci	else if (ops->request)
1688c2ecf20Sopenharmony_ci		status = ops->request(pctldev, pin);
1698c2ecf20Sopenharmony_ci	else
1708c2ecf20Sopenharmony_ci		status = 0;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	if (status) {
1738c2ecf20Sopenharmony_ci		dev_err(pctldev->dev, "request() failed for pin %d\n", pin);
1748c2ecf20Sopenharmony_ci		module_put(pctldev->owner);
1758c2ecf20Sopenharmony_ci	}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ciout_free_pin:
1788c2ecf20Sopenharmony_ci	if (status) {
1798c2ecf20Sopenharmony_ci		if (gpio_range) {
1808c2ecf20Sopenharmony_ci			desc->gpio_owner = NULL;
1818c2ecf20Sopenharmony_ci		} else {
1828c2ecf20Sopenharmony_ci			desc->mux_usecount--;
1838c2ecf20Sopenharmony_ci			if (!desc->mux_usecount)
1848c2ecf20Sopenharmony_ci				desc->mux_owner = NULL;
1858c2ecf20Sopenharmony_ci		}
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ciout:
1888c2ecf20Sopenharmony_ci	if (status)
1898c2ecf20Sopenharmony_ci		dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
1908c2ecf20Sopenharmony_ci			pin, owner, status);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	return status;
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci/**
1968c2ecf20Sopenharmony_ci * pin_free() - release a single muxed in pin so something else can be muxed
1978c2ecf20Sopenharmony_ci * @pctldev: pin controller device handling this pin
1988c2ecf20Sopenharmony_ci * @pin: the pin to free
1998c2ecf20Sopenharmony_ci * @gpio_range: the range matching the GPIO pin if this is a request for a
2008c2ecf20Sopenharmony_ci *	single GPIO pin
2018c2ecf20Sopenharmony_ci *
2028c2ecf20Sopenharmony_ci * This function returns a pointer to the previous owner. This is used
2038c2ecf20Sopenharmony_ci * for callers that dynamically allocate an owner name so it can be freed
2048c2ecf20Sopenharmony_ci * once the pin is free. This is done for GPIO request functions.
2058c2ecf20Sopenharmony_ci */
2068c2ecf20Sopenharmony_cistatic const char *pin_free(struct pinctrl_dev *pctldev, int pin,
2078c2ecf20Sopenharmony_ci			    struct pinctrl_gpio_range *gpio_range)
2088c2ecf20Sopenharmony_ci{
2098c2ecf20Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
2108c2ecf20Sopenharmony_ci	struct pin_desc *desc;
2118c2ecf20Sopenharmony_ci	const char *owner;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	desc = pin_desc_get(pctldev, pin);
2148c2ecf20Sopenharmony_ci	if (desc == NULL) {
2158c2ecf20Sopenharmony_ci		dev_err(pctldev->dev,
2168c2ecf20Sopenharmony_ci			"pin is not registered so it cannot be freed\n");
2178c2ecf20Sopenharmony_ci		return NULL;
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	if (!gpio_range) {
2218c2ecf20Sopenharmony_ci		/*
2228c2ecf20Sopenharmony_ci		 * A pin should not be freed more times than allocated.
2238c2ecf20Sopenharmony_ci		 */
2248c2ecf20Sopenharmony_ci		if (WARN_ON(!desc->mux_usecount))
2258c2ecf20Sopenharmony_ci			return NULL;
2268c2ecf20Sopenharmony_ci		desc->mux_usecount--;
2278c2ecf20Sopenharmony_ci		if (desc->mux_usecount)
2288c2ecf20Sopenharmony_ci			return NULL;
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/*
2328c2ecf20Sopenharmony_ci	 * If there is no kind of request function for the pin we just assume
2338c2ecf20Sopenharmony_ci	 * we got it by default and proceed.
2348c2ecf20Sopenharmony_ci	 */
2358c2ecf20Sopenharmony_ci	if (gpio_range && ops->gpio_disable_free)
2368c2ecf20Sopenharmony_ci		ops->gpio_disable_free(pctldev, gpio_range, pin);
2378c2ecf20Sopenharmony_ci	else if (ops->free)
2388c2ecf20Sopenharmony_ci		ops->free(pctldev, pin);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if (gpio_range) {
2418c2ecf20Sopenharmony_ci		owner = desc->gpio_owner;
2428c2ecf20Sopenharmony_ci		desc->gpio_owner = NULL;
2438c2ecf20Sopenharmony_ci	} else {
2448c2ecf20Sopenharmony_ci		owner = desc->mux_owner;
2458c2ecf20Sopenharmony_ci		desc->mux_owner = NULL;
2468c2ecf20Sopenharmony_ci		desc->mux_setting = NULL;
2478c2ecf20Sopenharmony_ci	}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	module_put(pctldev->owner);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	return owner;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci/**
2558c2ecf20Sopenharmony_ci * pinmux_request_gpio() - request pinmuxing for a GPIO pin
2568c2ecf20Sopenharmony_ci * @pctldev: pin controller device affected
2578c2ecf20Sopenharmony_ci * @pin: the pin to mux in for GPIO
2588c2ecf20Sopenharmony_ci * @range: the applicable GPIO range
2598c2ecf20Sopenharmony_ci * @gpio: number of requested GPIO
2608c2ecf20Sopenharmony_ci */
2618c2ecf20Sopenharmony_ciint pinmux_request_gpio(struct pinctrl_dev *pctldev,
2628c2ecf20Sopenharmony_ci			struct pinctrl_gpio_range *range,
2638c2ecf20Sopenharmony_ci			unsigned pin, unsigned gpio)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	const char *owner;
2668c2ecf20Sopenharmony_ci	int ret;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	/* Conjure some name stating what chip and pin this is taken by */
2698c2ecf20Sopenharmony_ci	owner = kasprintf(GFP_KERNEL, "%s:%d", range->name, gpio);
2708c2ecf20Sopenharmony_ci	if (!owner)
2718c2ecf20Sopenharmony_ci		return -ENOMEM;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	ret = pin_request(pctldev, pin, owner, range);
2748c2ecf20Sopenharmony_ci	if (ret < 0)
2758c2ecf20Sopenharmony_ci		kfree(owner);
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	return ret;
2788c2ecf20Sopenharmony_ci}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci/**
2818c2ecf20Sopenharmony_ci * pinmux_free_gpio() - release a pin from GPIO muxing
2828c2ecf20Sopenharmony_ci * @pctldev: the pin controller device for the pin
2838c2ecf20Sopenharmony_ci * @pin: the affected currently GPIO-muxed in pin
2848c2ecf20Sopenharmony_ci * @range: applicable GPIO range
2858c2ecf20Sopenharmony_ci */
2868c2ecf20Sopenharmony_civoid pinmux_free_gpio(struct pinctrl_dev *pctldev, unsigned pin,
2878c2ecf20Sopenharmony_ci		      struct pinctrl_gpio_range *range)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	const char *owner;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	owner = pin_free(pctldev, pin, range);
2928c2ecf20Sopenharmony_ci	kfree(owner);
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci/**
2968c2ecf20Sopenharmony_ci * pinmux_gpio_direction() - set the direction of a single muxed-in GPIO pin
2978c2ecf20Sopenharmony_ci * @pctldev: the pin controller handling this pin
2988c2ecf20Sopenharmony_ci * @range: applicable GPIO range
2998c2ecf20Sopenharmony_ci * @pin: the affected GPIO pin in this controller
3008c2ecf20Sopenharmony_ci * @input: true if we set the pin as input, false for output
3018c2ecf20Sopenharmony_ci */
3028c2ecf20Sopenharmony_ciint pinmux_gpio_direction(struct pinctrl_dev *pctldev,
3038c2ecf20Sopenharmony_ci			  struct pinctrl_gpio_range *range,
3048c2ecf20Sopenharmony_ci			  unsigned pin, bool input)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	const struct pinmux_ops *ops;
3078c2ecf20Sopenharmony_ci	int ret;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	ops = pctldev->desc->pmxops;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	if (ops->gpio_set_direction)
3128c2ecf20Sopenharmony_ci		ret = ops->gpio_set_direction(pctldev, range, pin, input);
3138c2ecf20Sopenharmony_ci	else
3148c2ecf20Sopenharmony_ci		ret = 0;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	return ret;
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_cistatic int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
3208c2ecf20Sopenharmony_ci					const char *function)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
3238c2ecf20Sopenharmony_ci	unsigned nfuncs = ops->get_functions_count(pctldev);
3248c2ecf20Sopenharmony_ci	unsigned selector = 0;
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	/* See if this pctldev has this function */
3278c2ecf20Sopenharmony_ci	while (selector < nfuncs) {
3288c2ecf20Sopenharmony_ci		const char *fname = ops->get_function_name(pctldev, selector);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci		if (!strcmp(function, fname))
3318c2ecf20Sopenharmony_ci			return selector;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci		selector++;
3348c2ecf20Sopenharmony_ci	}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	return -EINVAL;
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ciint pinmux_map_to_setting(const struct pinctrl_map *map,
3408c2ecf20Sopenharmony_ci			  struct pinctrl_setting *setting)
3418c2ecf20Sopenharmony_ci{
3428c2ecf20Sopenharmony_ci	struct pinctrl_dev *pctldev = setting->pctldev;
3438c2ecf20Sopenharmony_ci	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
3448c2ecf20Sopenharmony_ci	char const * const *groups;
3458c2ecf20Sopenharmony_ci	unsigned num_groups;
3468c2ecf20Sopenharmony_ci	int ret;
3478c2ecf20Sopenharmony_ci	const char *group;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	if (!pmxops) {
3508c2ecf20Sopenharmony_ci		dev_err(pctldev->dev, "does not support mux function\n");
3518c2ecf20Sopenharmony_ci		return -EINVAL;
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	ret = pinmux_func_name_to_selector(pctldev, map->data.mux.function);
3558c2ecf20Sopenharmony_ci	if (ret < 0) {
3568c2ecf20Sopenharmony_ci		dev_err(pctldev->dev, "invalid function %s in map table\n",
3578c2ecf20Sopenharmony_ci			map->data.mux.function);
3588c2ecf20Sopenharmony_ci		return ret;
3598c2ecf20Sopenharmony_ci	}
3608c2ecf20Sopenharmony_ci	setting->data.mux.func = ret;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
3638c2ecf20Sopenharmony_ci					  &groups, &num_groups);
3648c2ecf20Sopenharmony_ci	if (ret < 0) {
3658c2ecf20Sopenharmony_ci		dev_err(pctldev->dev, "can't query groups for function %s\n",
3668c2ecf20Sopenharmony_ci			map->data.mux.function);
3678c2ecf20Sopenharmony_ci		return ret;
3688c2ecf20Sopenharmony_ci	}
3698c2ecf20Sopenharmony_ci	if (!num_groups) {
3708c2ecf20Sopenharmony_ci		dev_err(pctldev->dev,
3718c2ecf20Sopenharmony_ci			"function %s can't be selected on any group\n",
3728c2ecf20Sopenharmony_ci			map->data.mux.function);
3738c2ecf20Sopenharmony_ci		return -EINVAL;
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci	if (map->data.mux.group) {
3768c2ecf20Sopenharmony_ci		group = map->data.mux.group;
3778c2ecf20Sopenharmony_ci		ret = match_string(groups, num_groups, group);
3788c2ecf20Sopenharmony_ci		if (ret < 0) {
3798c2ecf20Sopenharmony_ci			dev_err(pctldev->dev,
3808c2ecf20Sopenharmony_ci				"invalid group \"%s\" for function \"%s\"\n",
3818c2ecf20Sopenharmony_ci				group, map->data.mux.function);
3828c2ecf20Sopenharmony_ci			return ret;
3838c2ecf20Sopenharmony_ci		}
3848c2ecf20Sopenharmony_ci	} else {
3858c2ecf20Sopenharmony_ci		group = groups[0];
3868c2ecf20Sopenharmony_ci	}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	ret = pinctrl_get_group_selector(pctldev, group);
3898c2ecf20Sopenharmony_ci	if (ret < 0) {
3908c2ecf20Sopenharmony_ci		dev_err(pctldev->dev, "invalid group %s in map table\n",
3918c2ecf20Sopenharmony_ci			map->data.mux.group);
3928c2ecf20Sopenharmony_ci		return ret;
3938c2ecf20Sopenharmony_ci	}
3948c2ecf20Sopenharmony_ci	setting->data.mux.group = ret;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	return 0;
3978c2ecf20Sopenharmony_ci}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_civoid pinmux_free_setting(const struct pinctrl_setting *setting)
4008c2ecf20Sopenharmony_ci{
4018c2ecf20Sopenharmony_ci	/* This function is currently unused */
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ciint pinmux_enable_setting(const struct pinctrl_setting *setting)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	struct pinctrl_dev *pctldev = setting->pctldev;
4078c2ecf20Sopenharmony_ci	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
4088c2ecf20Sopenharmony_ci	const struct pinmux_ops *ops = pctldev->desc->pmxops;
4098c2ecf20Sopenharmony_ci	int ret = 0;
4108c2ecf20Sopenharmony_ci	const unsigned *pins = NULL;
4118c2ecf20Sopenharmony_ci	unsigned num_pins = 0;
4128c2ecf20Sopenharmony_ci	int i;
4138c2ecf20Sopenharmony_ci	struct pin_desc *desc;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	if (pctlops->get_group_pins)
4168c2ecf20Sopenharmony_ci		ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
4178c2ecf20Sopenharmony_ci					      &pins, &num_pins);
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	if (ret) {
4208c2ecf20Sopenharmony_ci		const char *gname;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci		/* errors only affect debug data, so just warn */
4238c2ecf20Sopenharmony_ci		gname = pctlops->get_group_name(pctldev,
4248c2ecf20Sopenharmony_ci						setting->data.mux.group);
4258c2ecf20Sopenharmony_ci		dev_warn(pctldev->dev,
4268c2ecf20Sopenharmony_ci			 "could not get pins for group %s\n",
4278c2ecf20Sopenharmony_ci			 gname);
4288c2ecf20Sopenharmony_ci		num_pins = 0;
4298c2ecf20Sopenharmony_ci	}
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	/* Try to allocate all pins in this group, one by one */
4328c2ecf20Sopenharmony_ci	for (i = 0; i < num_pins; i++) {
4338c2ecf20Sopenharmony_ci		ret = pin_request(pctldev, pins[i], setting->dev_name, NULL);
4348c2ecf20Sopenharmony_ci		if (ret) {
4358c2ecf20Sopenharmony_ci			const char *gname;
4368c2ecf20Sopenharmony_ci			const char *pname;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci			desc = pin_desc_get(pctldev, pins[i]);
4398c2ecf20Sopenharmony_ci			pname = desc ? desc->name : "non-existing";
4408c2ecf20Sopenharmony_ci			gname = pctlops->get_group_name(pctldev,
4418c2ecf20Sopenharmony_ci						setting->data.mux.group);
4428c2ecf20Sopenharmony_ci			dev_err(pctldev->dev,
4438c2ecf20Sopenharmony_ci				"could not request pin %d (%s) from group %s "
4448c2ecf20Sopenharmony_ci				" on device %s\n",
4458c2ecf20Sopenharmony_ci				pins[i], pname, gname,
4468c2ecf20Sopenharmony_ci				pinctrl_dev_get_name(pctldev));
4478c2ecf20Sopenharmony_ci			goto err_pin_request;
4488c2ecf20Sopenharmony_ci		}
4498c2ecf20Sopenharmony_ci	}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	/* Now that we have acquired the pins, encode the mux setting */
4528c2ecf20Sopenharmony_ci	for (i = 0; i < num_pins; i++) {
4538c2ecf20Sopenharmony_ci		desc = pin_desc_get(pctldev, pins[i]);
4548c2ecf20Sopenharmony_ci		if (desc == NULL) {
4558c2ecf20Sopenharmony_ci			dev_warn(pctldev->dev,
4568c2ecf20Sopenharmony_ci				 "could not get pin desc for pin %d\n",
4578c2ecf20Sopenharmony_ci				 pins[i]);
4588c2ecf20Sopenharmony_ci			continue;
4598c2ecf20Sopenharmony_ci		}
4608c2ecf20Sopenharmony_ci		desc->mux_setting = &(setting->data.mux);
4618c2ecf20Sopenharmony_ci	}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	ret = ops->set_mux(pctldev, setting->data.mux.func,
4648c2ecf20Sopenharmony_ci			   setting->data.mux.group);
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	if (ret)
4678c2ecf20Sopenharmony_ci		goto err_set_mux;
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	return 0;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cierr_set_mux:
4728c2ecf20Sopenharmony_ci	for (i = 0; i < num_pins; i++) {
4738c2ecf20Sopenharmony_ci		desc = pin_desc_get(pctldev, pins[i]);
4748c2ecf20Sopenharmony_ci		if (desc)
4758c2ecf20Sopenharmony_ci			desc->mux_setting = NULL;
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_cierr_pin_request:
4788c2ecf20Sopenharmony_ci	/* On error release all taken pins */
4798c2ecf20Sopenharmony_ci	while (--i >= 0)
4808c2ecf20Sopenharmony_ci		pin_free(pctldev, pins[i], NULL);
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	return ret;
4838c2ecf20Sopenharmony_ci}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_civoid pinmux_disable_setting(const struct pinctrl_setting *setting)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	struct pinctrl_dev *pctldev = setting->pctldev;
4888c2ecf20Sopenharmony_ci	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
4898c2ecf20Sopenharmony_ci	int ret = 0;
4908c2ecf20Sopenharmony_ci	const unsigned *pins = NULL;
4918c2ecf20Sopenharmony_ci	unsigned num_pins = 0;
4928c2ecf20Sopenharmony_ci	int i;
4938c2ecf20Sopenharmony_ci	struct pin_desc *desc;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	if (pctlops->get_group_pins)
4968c2ecf20Sopenharmony_ci		ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
4978c2ecf20Sopenharmony_ci					      &pins, &num_pins);
4988c2ecf20Sopenharmony_ci	if (ret) {
4998c2ecf20Sopenharmony_ci		const char *gname;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci		/* errors only affect debug data, so just warn */
5028c2ecf20Sopenharmony_ci		gname = pctlops->get_group_name(pctldev,
5038c2ecf20Sopenharmony_ci						setting->data.mux.group);
5048c2ecf20Sopenharmony_ci		dev_warn(pctldev->dev,
5058c2ecf20Sopenharmony_ci			 "could not get pins for group %s\n",
5068c2ecf20Sopenharmony_ci			 gname);
5078c2ecf20Sopenharmony_ci		num_pins = 0;
5088c2ecf20Sopenharmony_ci	}
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	/* Flag the descs that no setting is active */
5118c2ecf20Sopenharmony_ci	for (i = 0; i < num_pins; i++) {
5128c2ecf20Sopenharmony_ci		desc = pin_desc_get(pctldev, pins[i]);
5138c2ecf20Sopenharmony_ci		if (desc == NULL) {
5148c2ecf20Sopenharmony_ci			dev_warn(pctldev->dev,
5158c2ecf20Sopenharmony_ci				 "could not get pin desc for pin %d\n",
5168c2ecf20Sopenharmony_ci				 pins[i]);
5178c2ecf20Sopenharmony_ci			continue;
5188c2ecf20Sopenharmony_ci		}
5198c2ecf20Sopenharmony_ci		if (desc->mux_setting == &(setting->data.mux)) {
5208c2ecf20Sopenharmony_ci			pin_free(pctldev, pins[i], NULL);
5218c2ecf20Sopenharmony_ci		} else {
5228c2ecf20Sopenharmony_ci			const char *gname;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci			gname = pctlops->get_group_name(pctldev,
5258c2ecf20Sopenharmony_ci						setting->data.mux.group);
5268c2ecf20Sopenharmony_ci			dev_warn(pctldev->dev,
5278c2ecf20Sopenharmony_ci				 "not freeing pin %d (%s) as part of "
5288c2ecf20Sopenharmony_ci				 "deactivating group %s - it is already "
5298c2ecf20Sopenharmony_ci				 "used for some other setting",
5308c2ecf20Sopenharmony_ci				 pins[i], desc->name, gname);
5318c2ecf20Sopenharmony_ci		}
5328c2ecf20Sopenharmony_ci	}
5338c2ecf20Sopenharmony_ci}
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci/* Called from pincontrol core */
5388c2ecf20Sopenharmony_cistatic int pinmux_functions_show(struct seq_file *s, void *what)
5398c2ecf20Sopenharmony_ci{
5408c2ecf20Sopenharmony_ci	struct pinctrl_dev *pctldev = s->private;
5418c2ecf20Sopenharmony_ci	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
5428c2ecf20Sopenharmony_ci	unsigned nfuncs;
5438c2ecf20Sopenharmony_ci	unsigned func_selector = 0;
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	if (!pmxops)
5468c2ecf20Sopenharmony_ci		return 0;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	mutex_lock(&pctldev->mutex);
5498c2ecf20Sopenharmony_ci	nfuncs = pmxops->get_functions_count(pctldev);
5508c2ecf20Sopenharmony_ci	while (func_selector < nfuncs) {
5518c2ecf20Sopenharmony_ci		const char *func = pmxops->get_function_name(pctldev,
5528c2ecf20Sopenharmony_ci							  func_selector);
5538c2ecf20Sopenharmony_ci		const char * const *groups;
5548c2ecf20Sopenharmony_ci		unsigned num_groups;
5558c2ecf20Sopenharmony_ci		int ret;
5568c2ecf20Sopenharmony_ci		int i;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci		ret = pmxops->get_function_groups(pctldev, func_selector,
5598c2ecf20Sopenharmony_ci						  &groups, &num_groups);
5608c2ecf20Sopenharmony_ci		if (ret) {
5618c2ecf20Sopenharmony_ci			seq_printf(s, "function %s: COULD NOT GET GROUPS\n",
5628c2ecf20Sopenharmony_ci				   func);
5638c2ecf20Sopenharmony_ci			func_selector++;
5648c2ecf20Sopenharmony_ci			continue;
5658c2ecf20Sopenharmony_ci		}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci		seq_printf(s, "function: %s, groups = [ ", func);
5688c2ecf20Sopenharmony_ci		for (i = 0; i < num_groups; i++)
5698c2ecf20Sopenharmony_ci			seq_printf(s, "%s ", groups[i]);
5708c2ecf20Sopenharmony_ci		seq_puts(s, "]\n");
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci		func_selector++;
5738c2ecf20Sopenharmony_ci	}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	mutex_unlock(&pctldev->mutex);
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	return 0;
5788c2ecf20Sopenharmony_ci}
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_cistatic int pinmux_pins_show(struct seq_file *s, void *what)
5818c2ecf20Sopenharmony_ci{
5828c2ecf20Sopenharmony_ci	struct pinctrl_dev *pctldev = s->private;
5838c2ecf20Sopenharmony_ci	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
5848c2ecf20Sopenharmony_ci	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
5858c2ecf20Sopenharmony_ci	unsigned i, pin;
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	if (!pmxops)
5888c2ecf20Sopenharmony_ci		return 0;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	seq_puts(s, "Pinmux settings per pin\n");
5918c2ecf20Sopenharmony_ci	if (pmxops->strict)
5928c2ecf20Sopenharmony_ci		seq_puts(s,
5938c2ecf20Sopenharmony_ci		 "Format: pin (name): mux_owner|gpio_owner (strict) hog?\n");
5948c2ecf20Sopenharmony_ci	else
5958c2ecf20Sopenharmony_ci		seq_puts(s,
5968c2ecf20Sopenharmony_ci		"Format: pin (name): mux_owner gpio_owner hog?\n");
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	mutex_lock(&pctldev->mutex);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	/* The pin number can be retrived from the pin controller descriptor */
6018c2ecf20Sopenharmony_ci	for (i = 0; i < pctldev->desc->npins; i++) {
6028c2ecf20Sopenharmony_ci		struct pin_desc *desc;
6038c2ecf20Sopenharmony_ci		bool is_hog = false;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci		pin = pctldev->desc->pins[i].number;
6068c2ecf20Sopenharmony_ci		desc = pin_desc_get(pctldev, pin);
6078c2ecf20Sopenharmony_ci		/* Skip if we cannot search the pin */
6088c2ecf20Sopenharmony_ci		if (desc == NULL)
6098c2ecf20Sopenharmony_ci			continue;
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci		if (desc->mux_owner &&
6128c2ecf20Sopenharmony_ci		    !strcmp(desc->mux_owner, pinctrl_dev_get_name(pctldev)))
6138c2ecf20Sopenharmony_ci			is_hog = true;
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci		if (pmxops->strict) {
6168c2ecf20Sopenharmony_ci			if (desc->mux_owner)
6178c2ecf20Sopenharmony_ci				seq_printf(s, "pin %d (%s): device %s%s",
6188c2ecf20Sopenharmony_ci					   pin, desc->name, desc->mux_owner,
6198c2ecf20Sopenharmony_ci					   is_hog ? " (HOG)" : "");
6208c2ecf20Sopenharmony_ci			else if (desc->gpio_owner)
6218c2ecf20Sopenharmony_ci				seq_printf(s, "pin %d (%s): GPIO %s",
6228c2ecf20Sopenharmony_ci					   pin, desc->name, desc->gpio_owner);
6238c2ecf20Sopenharmony_ci			else
6248c2ecf20Sopenharmony_ci				seq_printf(s, "pin %d (%s): UNCLAIMED",
6258c2ecf20Sopenharmony_ci					   pin, desc->name);
6268c2ecf20Sopenharmony_ci		} else {
6278c2ecf20Sopenharmony_ci			/* For non-strict controllers */
6288c2ecf20Sopenharmony_ci			seq_printf(s, "pin %d (%s): %s %s%s", pin, desc->name,
6298c2ecf20Sopenharmony_ci				   desc->mux_owner ? desc->mux_owner
6308c2ecf20Sopenharmony_ci				   : "(MUX UNCLAIMED)",
6318c2ecf20Sopenharmony_ci				   desc->gpio_owner ? desc->gpio_owner
6328c2ecf20Sopenharmony_ci				   : "(GPIO UNCLAIMED)",
6338c2ecf20Sopenharmony_ci				   is_hog ? " (HOG)" : "");
6348c2ecf20Sopenharmony_ci		}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci		/* If mux: print function+group claiming the pin */
6378c2ecf20Sopenharmony_ci		if (desc->mux_setting)
6388c2ecf20Sopenharmony_ci			seq_printf(s, " function %s group %s\n",
6398c2ecf20Sopenharmony_ci				   pmxops->get_function_name(pctldev,
6408c2ecf20Sopenharmony_ci					desc->mux_setting->func),
6418c2ecf20Sopenharmony_ci				   pctlops->get_group_name(pctldev,
6428c2ecf20Sopenharmony_ci					desc->mux_setting->group));
6438c2ecf20Sopenharmony_ci		else
6448c2ecf20Sopenharmony_ci			seq_putc(s, '\n');
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	mutex_unlock(&pctldev->mutex);
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	return 0;
6508c2ecf20Sopenharmony_ci}
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_civoid pinmux_show_map(struct seq_file *s, const struct pinctrl_map *map)
6538c2ecf20Sopenharmony_ci{
6548c2ecf20Sopenharmony_ci	seq_printf(s, "group %s\nfunction %s\n",
6558c2ecf20Sopenharmony_ci		map->data.mux.group ? map->data.mux.group : "(default)",
6568c2ecf20Sopenharmony_ci		map->data.mux.function);
6578c2ecf20Sopenharmony_ci}
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_civoid pinmux_show_setting(struct seq_file *s,
6608c2ecf20Sopenharmony_ci			 const struct pinctrl_setting *setting)
6618c2ecf20Sopenharmony_ci{
6628c2ecf20Sopenharmony_ci	struct pinctrl_dev *pctldev = setting->pctldev;
6638c2ecf20Sopenharmony_ci	const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
6648c2ecf20Sopenharmony_ci	const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	seq_printf(s, "group: %s (%u) function: %s (%u)\n",
6678c2ecf20Sopenharmony_ci		   pctlops->get_group_name(pctldev, setting->data.mux.group),
6688c2ecf20Sopenharmony_ci		   setting->data.mux.group,
6698c2ecf20Sopenharmony_ci		   pmxops->get_function_name(pctldev, setting->data.mux.func),
6708c2ecf20Sopenharmony_ci		   setting->data.mux.func);
6718c2ecf20Sopenharmony_ci}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(pinmux_functions);
6748c2ecf20Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(pinmux_pins);
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_civoid pinmux_init_device_debugfs(struct dentry *devroot,
6778c2ecf20Sopenharmony_ci			 struct pinctrl_dev *pctldev)
6788c2ecf20Sopenharmony_ci{
6798c2ecf20Sopenharmony_ci	debugfs_create_file("pinmux-functions", S_IFREG | S_IRUGO,
6808c2ecf20Sopenharmony_ci			    devroot, pctldev, &pinmux_functions_fops);
6818c2ecf20Sopenharmony_ci	debugfs_create_file("pinmux-pins", S_IFREG | S_IRUGO,
6828c2ecf20Sopenharmony_ci			    devroot, pctldev, &pinmux_pins_fops);
6838c2ecf20Sopenharmony_ci}
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci#ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci/**
6908c2ecf20Sopenharmony_ci * pinmux_generic_get_function_count() - returns number of functions
6918c2ecf20Sopenharmony_ci * @pctldev: pin controller device
6928c2ecf20Sopenharmony_ci */
6938c2ecf20Sopenharmony_ciint pinmux_generic_get_function_count(struct pinctrl_dev *pctldev)
6948c2ecf20Sopenharmony_ci{
6958c2ecf20Sopenharmony_ci	return pctldev->num_functions;
6968c2ecf20Sopenharmony_ci}
6978c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_get_function_count);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci/**
7008c2ecf20Sopenharmony_ci * pinmux_generic_get_function_name() - returns the function name
7018c2ecf20Sopenharmony_ci * @pctldev: pin controller device
7028c2ecf20Sopenharmony_ci * @selector: function number
7038c2ecf20Sopenharmony_ci */
7048c2ecf20Sopenharmony_ciconst char *
7058c2ecf20Sopenharmony_cipinmux_generic_get_function_name(struct pinctrl_dev *pctldev,
7068c2ecf20Sopenharmony_ci				 unsigned int selector)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	struct function_desc *function;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	function = radix_tree_lookup(&pctldev->pin_function_tree,
7118c2ecf20Sopenharmony_ci				     selector);
7128c2ecf20Sopenharmony_ci	if (!function)
7138c2ecf20Sopenharmony_ci		return NULL;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	return function->name;
7168c2ecf20Sopenharmony_ci}
7178c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_get_function_name);
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci/**
7208c2ecf20Sopenharmony_ci * pinmux_generic_get_function_groups() - gets the function groups
7218c2ecf20Sopenharmony_ci * @pctldev: pin controller device
7228c2ecf20Sopenharmony_ci * @selector: function number
7238c2ecf20Sopenharmony_ci * @groups: array of pin groups
7248c2ecf20Sopenharmony_ci * @num_groups: number of pin groups
7258c2ecf20Sopenharmony_ci */
7268c2ecf20Sopenharmony_ciint pinmux_generic_get_function_groups(struct pinctrl_dev *pctldev,
7278c2ecf20Sopenharmony_ci				       unsigned int selector,
7288c2ecf20Sopenharmony_ci				       const char * const **groups,
7298c2ecf20Sopenharmony_ci				       unsigned * const num_groups)
7308c2ecf20Sopenharmony_ci{
7318c2ecf20Sopenharmony_ci	struct function_desc *function;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	function = radix_tree_lookup(&pctldev->pin_function_tree,
7348c2ecf20Sopenharmony_ci				     selector);
7358c2ecf20Sopenharmony_ci	if (!function) {
7368c2ecf20Sopenharmony_ci		dev_err(pctldev->dev, "%s could not find function%i\n",
7378c2ecf20Sopenharmony_ci			__func__, selector);
7388c2ecf20Sopenharmony_ci		return -EINVAL;
7398c2ecf20Sopenharmony_ci	}
7408c2ecf20Sopenharmony_ci	*groups = function->group_names;
7418c2ecf20Sopenharmony_ci	*num_groups = function->num_group_names;
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	return 0;
7448c2ecf20Sopenharmony_ci}
7458c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_get_function_groups);
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci/**
7488c2ecf20Sopenharmony_ci * pinmux_generic_get_function() - returns a function based on the number
7498c2ecf20Sopenharmony_ci * @pctldev: pin controller device
7508c2ecf20Sopenharmony_ci * @selector: function number
7518c2ecf20Sopenharmony_ci */
7528c2ecf20Sopenharmony_cistruct function_desc *pinmux_generic_get_function(struct pinctrl_dev *pctldev,
7538c2ecf20Sopenharmony_ci						  unsigned int selector)
7548c2ecf20Sopenharmony_ci{
7558c2ecf20Sopenharmony_ci	struct function_desc *function;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	function = radix_tree_lookup(&pctldev->pin_function_tree,
7588c2ecf20Sopenharmony_ci				     selector);
7598c2ecf20Sopenharmony_ci	if (!function)
7608c2ecf20Sopenharmony_ci		return NULL;
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	return function;
7638c2ecf20Sopenharmony_ci}
7648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_get_function);
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci/**
7678c2ecf20Sopenharmony_ci * pinmux_generic_add_function() - adds a function group
7688c2ecf20Sopenharmony_ci * @pctldev: pin controller device
7698c2ecf20Sopenharmony_ci * @name: name of the function
7708c2ecf20Sopenharmony_ci * @groups: array of pin groups
7718c2ecf20Sopenharmony_ci * @num_groups: number of pin groups
7728c2ecf20Sopenharmony_ci * @data: pin controller driver specific data
7738c2ecf20Sopenharmony_ci */
7748c2ecf20Sopenharmony_ciint pinmux_generic_add_function(struct pinctrl_dev *pctldev,
7758c2ecf20Sopenharmony_ci				const char *name,
7768c2ecf20Sopenharmony_ci				const char **groups,
7778c2ecf20Sopenharmony_ci				const unsigned int num_groups,
7788c2ecf20Sopenharmony_ci				void *data)
7798c2ecf20Sopenharmony_ci{
7808c2ecf20Sopenharmony_ci	struct function_desc *function;
7818c2ecf20Sopenharmony_ci	int selector;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	if (!name)
7848c2ecf20Sopenharmony_ci		return -EINVAL;
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	selector = pinmux_func_name_to_selector(pctldev, name);
7878c2ecf20Sopenharmony_ci	if (selector >= 0)
7888c2ecf20Sopenharmony_ci		return selector;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	selector = pctldev->num_functions;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	function = devm_kzalloc(pctldev->dev, sizeof(*function), GFP_KERNEL);
7938c2ecf20Sopenharmony_ci	if (!function)
7948c2ecf20Sopenharmony_ci		return -ENOMEM;
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	function->name = name;
7978c2ecf20Sopenharmony_ci	function->group_names = groups;
7988c2ecf20Sopenharmony_ci	function->num_group_names = num_groups;
7998c2ecf20Sopenharmony_ci	function->data = data;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	radix_tree_insert(&pctldev->pin_function_tree, selector, function);
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	pctldev->num_functions++;
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	return selector;
8068c2ecf20Sopenharmony_ci}
8078c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_add_function);
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci/**
8108c2ecf20Sopenharmony_ci * pinmux_generic_remove_function() - removes a numbered function
8118c2ecf20Sopenharmony_ci * @pctldev: pin controller device
8128c2ecf20Sopenharmony_ci * @selector: function number
8138c2ecf20Sopenharmony_ci *
8148c2ecf20Sopenharmony_ci * Note that the caller must take care of locking.
8158c2ecf20Sopenharmony_ci */
8168c2ecf20Sopenharmony_ciint pinmux_generic_remove_function(struct pinctrl_dev *pctldev,
8178c2ecf20Sopenharmony_ci				   unsigned int selector)
8188c2ecf20Sopenharmony_ci{
8198c2ecf20Sopenharmony_ci	struct function_desc *function;
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	function = radix_tree_lookup(&pctldev->pin_function_tree,
8228c2ecf20Sopenharmony_ci				     selector);
8238c2ecf20Sopenharmony_ci	if (!function)
8248c2ecf20Sopenharmony_ci		return -ENOENT;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	radix_tree_delete(&pctldev->pin_function_tree, selector);
8278c2ecf20Sopenharmony_ci	devm_kfree(pctldev->dev, function);
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	pctldev->num_functions--;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	return 0;
8328c2ecf20Sopenharmony_ci}
8338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(pinmux_generic_remove_function);
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci/**
8368c2ecf20Sopenharmony_ci * pinmux_generic_free_functions() - removes all functions
8378c2ecf20Sopenharmony_ci * @pctldev: pin controller device
8388c2ecf20Sopenharmony_ci *
8398c2ecf20Sopenharmony_ci * Note that the caller must take care of locking. The pinctrl
8408c2ecf20Sopenharmony_ci * functions are allocated with devm_kzalloc() so no need to free
8418c2ecf20Sopenharmony_ci * them here.
8428c2ecf20Sopenharmony_ci */
8438c2ecf20Sopenharmony_civoid pinmux_generic_free_functions(struct pinctrl_dev *pctldev)
8448c2ecf20Sopenharmony_ci{
8458c2ecf20Sopenharmony_ci	struct radix_tree_iter iter;
8468c2ecf20Sopenharmony_ci	void __rcu **slot;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	radix_tree_for_each_slot(slot, &pctldev->pin_function_tree, &iter, 0)
8498c2ecf20Sopenharmony_ci		radix_tree_delete(&pctldev->pin_function_tree, iter.index);
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	pctldev->num_functions = 0;
8528c2ecf20Sopenharmony_ci}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci#endif /* CONFIG_GENERIC_PINMUX_FUNCTIONS */
855