forked from Minki/linux
pinctrl: enhance pinctrl_get() to handle multiple functions
At present, pinctrl_get() assumes that all matching mapping table entries have the same "function" value, albeit potentially applied to different pins/groups. This change removes this restriction; pinctrl_get() can now handle a set of mapping tables where different functions are applied to the various pins/groups. Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
3eedb43723
commit
d4e3198736
@ -53,8 +53,6 @@ struct pinctrl_dev {
|
|||||||
* to keep track of nested use cases
|
* to keep track of nested use cases
|
||||||
* @pctldev: pin control device handling this pin control handle
|
* @pctldev: pin control device handling this pin control handle
|
||||||
* @mutex: a lock for the pin control state holder
|
* @mutex: a lock for the pin control state holder
|
||||||
* @func_selector: the function selector for the pinmux device handling
|
|
||||||
* this pinmux
|
|
||||||
* @groups: the group selectors for the pinmux device and
|
* @groups: the group selectors for the pinmux device and
|
||||||
* selector combination handling this pinmux, this is a list that
|
* selector combination handling this pinmux, this is a list that
|
||||||
* will be traversed on all pinmux operations such as
|
* will be traversed on all pinmux operations such as
|
||||||
@ -67,7 +65,6 @@ struct pinctrl {
|
|||||||
struct pinctrl_dev *pctldev;
|
struct pinctrl_dev *pctldev;
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
#ifdef CONFIG_PINMUX
|
#ifdef CONFIG_PINMUX
|
||||||
unsigned func_selector;
|
|
||||||
struct list_head groups;
|
struct list_head groups;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -33,10 +33,13 @@
|
|||||||
/**
|
/**
|
||||||
* struct pinmux_group - group list item for pinmux groups
|
* struct pinmux_group - group list item for pinmux groups
|
||||||
* @node: pinmux group list node
|
* @node: pinmux group list node
|
||||||
|
* @func_selector: the function selector for the pinmux device handling
|
||||||
|
* this pinmux
|
||||||
* @group_selector: the group selector for this group
|
* @group_selector: the group selector for this group
|
||||||
*/
|
*/
|
||||||
struct pinmux_group {
|
struct pinmux_group {
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
|
unsigned func_selector;
|
||||||
unsigned group_selector;
|
unsigned group_selector;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -476,24 +479,11 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/*
|
|
||||||
* If the function selector is already set, it needs to be identical,
|
|
||||||
* we support several groups with one function but not several
|
|
||||||
* functions with one or several groups in the same pinmux.
|
|
||||||
*/
|
|
||||||
if (p->func_selector != UINT_MAX &&
|
|
||||||
p->func_selector != func_selector) {
|
|
||||||
dev_err(pctldev->dev,
|
|
||||||
"dual function defines in the map for device %s\n",
|
|
||||||
devname);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
p->func_selector = func_selector;
|
|
||||||
|
|
||||||
/* Now add this group selector, we may have many of them */
|
/* Now add this group selector, we may have many of them */
|
||||||
grp = kmalloc(sizeof(*grp), GFP_KERNEL);
|
grp = kmalloc(sizeof(*grp), GFP_KERNEL);
|
||||||
if (!grp)
|
if (!grp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
grp->func_selector = func_selector;
|
||||||
grp->group_selector = group_selector;
|
grp->group_selector = group_selector;
|
||||||
ret = acquire_pins(pctldev, devname, group_selector);
|
ret = acquire_pins(pctldev, devname, group_selector);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -554,7 +544,7 @@ int pinmux_enable(struct pinctrl *p)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
list_for_each_entry(grp, &p->groups, node) {
|
list_for_each_entry(grp, &p->groups, node) {
|
||||||
ret = ops->enable(pctldev, p->func_selector,
|
ret = ops->enable(pctldev, grp->func_selector,
|
||||||
grp->group_selector);
|
grp->group_selector);
|
||||||
if (ret)
|
if (ret)
|
||||||
/*
|
/*
|
||||||
@ -576,7 +566,7 @@ void pinmux_disable(struct pinctrl *p)
|
|||||||
struct pinmux_group *grp;
|
struct pinmux_group *grp;
|
||||||
|
|
||||||
list_for_each_entry(grp, &p->groups, node) {
|
list_for_each_entry(grp, &p->groups, node) {
|
||||||
ops->disable(pctldev, p->func_selector,
|
ops->disable(pctldev, grp->func_selector,
|
||||||
grp->group_selector);
|
grp->group_selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -654,21 +644,22 @@ void pinmux_dbg_show(struct seq_file *s, struct pinctrl *p)
|
|||||||
const struct pinmux_ops *pmxops;
|
const struct pinmux_ops *pmxops;
|
||||||
const struct pinctrl_ops *pctlops;
|
const struct pinctrl_ops *pctlops;
|
||||||
struct pinmux_group *grp;
|
struct pinmux_group *grp;
|
||||||
|
const char *sep = "";
|
||||||
|
|
||||||
pmxops = pctldev->desc->pmxops;
|
pmxops = pctldev->desc->pmxops;
|
||||||
pctlops = pctldev->desc->pctlops;
|
pctlops = pctldev->desc->pctlops;
|
||||||
|
|
||||||
seq_printf(s, " function: %s (%u),",
|
|
||||||
pmxops->get_function_name(pctldev,
|
|
||||||
p->func_selector),
|
|
||||||
p->func_selector);
|
|
||||||
|
|
||||||
seq_printf(s, " groups: [");
|
seq_printf(s, " groups: [");
|
||||||
list_for_each_entry(grp, &p->groups, node) {
|
list_for_each_entry(grp, &p->groups, node) {
|
||||||
seq_printf(s, " %s (%u)",
|
seq_printf(s, "%s%s (%u)=%s (%u)",
|
||||||
|
sep,
|
||||||
pctlops->get_group_name(pctldev,
|
pctlops->get_group_name(pctldev,
|
||||||
grp->group_selector),
|
grp->group_selector),
|
||||||
grp->group_selector);
|
grp->group_selector,
|
||||||
|
pmxops->get_function_name(pctldev,
|
||||||
|
grp->func_selector),
|
||||||
|
grp->func_selector);
|
||||||
|
sep = ", ";
|
||||||
}
|
}
|
||||||
seq_printf(s, " ]");
|
seq_printf(s, " ]");
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ int pinmux_gpio_direction(struct pinctrl_dev *pctldev,
|
|||||||
unsigned pin, bool input);
|
unsigned pin, bool input);
|
||||||
static inline void pinmux_init_pinctrl_handle(struct pinctrl *p)
|
static inline void pinmux_init_pinctrl_handle(struct pinctrl *p)
|
||||||
{
|
{
|
||||||
p->func_selector = UINT_MAX;
|
|
||||||
INIT_LIST_HEAD(&p->groups);
|
INIT_LIST_HEAD(&p->groups);
|
||||||
}
|
}
|
||||||
int pinmux_apply_muxmap(struct pinctrl_dev *pctldev,
|
int pinmux_apply_muxmap(struct pinctrl_dev *pctldev,
|
||||||
|
Loading…
Reference in New Issue
Block a user