mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
pinctrl: single: Use generic pinmux helpers for managing functions
We can now drop the driver specific code for managing functions. Signed-off-by: Tony Lindgren <tony@atomide.com> [Replaces GENERIC_PINMUX with GENERIC_PINMUX_FUNCTIONS] Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
caeb774ea3
commit
571aec4df5
@ -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.
|
||||
|
@ -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 @@ free_pingroups:
|
||||
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 @@ free_pingroups:
|
||||
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 @@ free_map:
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user