Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 571aec4d authored by Tony Lindgren's avatar Tony Lindgren Committed by Linus Walleij
Browse files

pinctrl: single: Use generic pinmux helpers for managing functions



We can now drop the driver specific code for managing functions.

Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
[Replaces GENERIC_PINMUX with GENERIC_PINMUX_FUNCTIONS]
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent caeb774e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ config PINCTRL_SINGLE
	tristate "One-register-per-pin type device tree based pinctrl driver"
	depends on OF
	select GENERIC_PINCTRL_GROUPS
	select PINMUX
	select GENERIC_PINMUX_FUNCTIONS
	select GENERIC_PINCONF
	help
	  This selects the device tree based generic pinctrl driver.
+18 −116
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include "core.h"
#include "devicetree.h"
#include "pinconf.h"
#include "pinmux.h"

#define DRIVER_NAME			"pinctrl-single"
#define PCS_OFF_DISABLED		~0U
@@ -160,13 +161,10 @@ struct pcs_soc_data {
 * @bits_per_mux: number of bits per mux
 * @bits_per_pin: number of bits per pin
 * @pins:	physical pins on the SoC
 * @ftree:	function index radix tree
 * @functions:	list of functions
 * @gpiofuncs:	list of gpio functions
 * @irqs:	list of interrupt registers
 * @chip:	chip container for this instance
 * @domain:	IRQ domain for this instance
 * @nfuncs:	number of functions
 * @desc:	pin controller descriptor
 * @read:	register read function to use
 * @write:	register write function to use
@@ -194,13 +192,10 @@ struct pcs_device {
	bool bits_per_mux;
	unsigned bits_per_pin;
	struct pcs_data pins;
	struct radix_tree_root ftree;
	struct list_head functions;
	struct list_head gpiofuncs;
	struct list_head irqs;
	struct irq_chip chip;
	struct irq_domain *domain;
	unsigned nfuncs;
	struct pinctrl_desc desc;
	unsigned (*read)(void __iomem *reg);
	void (*write)(unsigned val, void __iomem *reg);
@@ -307,59 +302,13 @@ static const struct pinctrl_ops pcs_pinctrl_ops = {
	.dt_free_map = pcs_dt_free_map,
};

static int pcs_get_functions_count(struct pinctrl_dev *pctldev)
{
	struct pcs_device *pcs;

	pcs = pinctrl_dev_get_drvdata(pctldev);

	return pcs->nfuncs;
}

static const char *pcs_get_function_name(struct pinctrl_dev *pctldev,
						unsigned fselector)
{
	struct pcs_device *pcs;
	struct pcs_function *func;

	pcs = pinctrl_dev_get_drvdata(pctldev);
	func = radix_tree_lookup(&pcs->ftree, fselector);
	if (!func) {
		dev_err(pcs->dev, "%s could not find function%i\n",
			__func__, fselector);
		return NULL;
	}

	return func->name;
}

static int pcs_get_function_groups(struct pinctrl_dev *pctldev,
					unsigned fselector,
					const char * const **groups,
					unsigned * const ngroups)
{
	struct pcs_device *pcs;
	struct pcs_function *func;

	pcs = pinctrl_dev_get_drvdata(pctldev);
	func = radix_tree_lookup(&pcs->ftree, fselector);
	if (!func) {
		dev_err(pcs->dev, "%s could not find function%i\n",
			__func__, fselector);
		return -EINVAL;
	}
	*groups = func->pgnames;
	*ngroups = func->npgnames;

	return 0;
}

static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
			    struct pcs_function **func)
{
	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
	struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
	const struct pinctrl_setting_mux *setting;
	struct function_desc *function;
	unsigned fselector;

	/* If pin is not described in DTS & enabled, mux_setting is NULL. */
@@ -367,7 +316,8 @@ static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
	if (!setting)
		return -ENOTSUPP;
	fselector = setting->func;
	*func = radix_tree_lookup(&pcs->ftree, fselector);
	function = pinmux_generic_get_function(pctldev, fselector);
	*func = function->data;
	if (!(*func)) {
		dev_err(pcs->dev, "%s could not find function%i\n",
			__func__, fselector);
@@ -380,6 +330,7 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
	unsigned group)
{
	struct pcs_device *pcs;
	struct function_desc *function;
	struct pcs_function *func;
	int i;

@@ -387,7 +338,8 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
	/* If function mask is null, needn't enable it. */
	if (!pcs->fmask)
		return 0;
	func = radix_tree_lookup(&pcs->ftree, fselector);
	function = pinmux_generic_get_function(pctldev, fselector);
	func = function->data;
	if (!func)
		return -EINVAL;

@@ -445,9 +397,9 @@ static int pcs_request_gpio(struct pinctrl_dev *pctldev,
}

static const struct pinmux_ops pcs_pinmux_ops = {
	.get_functions_count = pcs_get_functions_count,
	.get_function_name = pcs_get_function_name,
	.get_function_groups = pcs_get_function_groups,
	.get_functions_count = pinmux_generic_get_function_count,
	.get_function_name = pinmux_generic_get_function_name,
	.get_function_groups = pinmux_generic_get_function_groups,
	.set_mux = pcs_set_mux,
	.gpio_request_enable = pcs_request_gpio,
};
@@ -789,43 +741,24 @@ static struct pcs_function *pcs_add_function(struct pcs_device *pcs,
					unsigned npgnames)
{
	struct pcs_function *function;
	int res;

	function = devm_kzalloc(pcs->dev, sizeof(*function), GFP_KERNEL);
	if (!function)
		return NULL;

	function->name = name;
	function->vals = vals;
	function->nvals = nvals;
	function->pgnames = pgnames;
	function->npgnames = npgnames;

	mutex_lock(&pcs->mutex);
	list_add_tail(&function->node, &pcs->functions);
	radix_tree_insert(&pcs->ftree, pcs->nfuncs, function);
	pcs->nfuncs++;
	mutex_unlock(&pcs->mutex);
	res = pinmux_generic_add_function(pcs->pctl, name,
					  pgnames, npgnames,
					  function);
	if (res)
		return NULL;

	return function;
}

static void pcs_remove_function(struct pcs_device *pcs,
				struct pcs_function *function)
{
	int i;

	mutex_lock(&pcs->mutex);
	for (i = 0; i < pcs->nfuncs; i++) {
		struct pcs_function *found;

		found = radix_tree_lookup(&pcs->ftree, i);
		if (found == function)
			radix_tree_delete(&pcs->ftree, i);
	}
	list_del(&function->node);
	mutex_unlock(&pcs->mutex);
}

/**
 * pcs_get_pin_by_offset() - get a pin index based on the register offset
 * @pcs: pcs driver instance
@@ -1103,7 +1036,7 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
	pinctrl_generic_remove_last_group(pcs->pctl);
	*num_maps = 1;
free_function:
	pcs_remove_function(pcs, function);
	pinmux_generic_remove_last_function(pcs->pctl);

free_pins:
	devm_kfree(pcs->dev, pins);
@@ -1235,8 +1168,7 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
	pinctrl_generic_remove_last_group(pcs->pctl);
	*num_maps = 1;
free_function:
	pcs_remove_function(pcs, function);

	pinmux_generic_remove_last_function(pcs->pctl);
free_pins:
	devm_kfree(pcs->dev, pins);

@@ -1303,33 +1235,6 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
	return ret;
}

/**
 * pcs_free_funcs() - free memory used by functions
 * @pcs: pcs driver instance
 */
static void pcs_free_funcs(struct pcs_device *pcs)
{
	struct list_head *pos, *tmp;
	int i;

	mutex_lock(&pcs->mutex);
	for (i = 0; i < pcs->nfuncs; i++) {
		struct pcs_function *func;

		func = radix_tree_lookup(&pcs->ftree, i);
		if (!func)
			continue;
		radix_tree_delete(&pcs->ftree, i);
	}
	list_for_each_safe(pos, tmp, &pcs->functions) {
		struct pcs_function *function;

		function = list_entry(pos, struct pcs_function, node);
		list_del(&function->node);
	}
	mutex_unlock(&pcs->mutex);
}

/**
 * pcs_irq_free() - free interrupt
 * @pcs: pcs driver instance
@@ -1358,7 +1263,6 @@ static void pcs_free_resources(struct pcs_device *pcs)
{
	pcs_irq_free(pcs);
	pinctrl_unregister(pcs->pctl);
	pcs_free_funcs(pcs);

#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
	if (pcs->missing_nr_pinctrl_cells)
@@ -1753,7 +1657,6 @@ static int pcs_probe(struct platform_device *pdev)
	pcs->np = np;
	raw_spin_lock_init(&pcs->lock);
	mutex_init(&pcs->mutex);
	INIT_LIST_HEAD(&pcs->functions);
	INIT_LIST_HEAD(&pcs->gpiofuncs);
	soc = match->data;
	pcs->flags = soc->flags;
@@ -1814,7 +1717,6 @@ static int pcs_probe(struct platform_device *pdev)
		return -ENODEV;
	}

	INIT_RADIX_TREE(&pcs->ftree, GFP_KERNEL);
	platform_set_drvdata(pdev, pcs);

	switch (pcs->width) {