diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-03-01 20:48:31 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-03-02 10:12:03 -0500 |
commit | d4e3198736d9d64e4ba4d2b46ab75cbcf5d0a4e0 (patch) | |
tree | e5e06f5c3ec83949e10f5407a1020ff5e07a7934 /drivers/pinctrl | |
parent | 3eedb4372354a70ce63c9f4ec294d2eba0d79d17 (diff) |
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>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/core.h | 3 | ||||
-rw-r--r-- | drivers/pinctrl/pinmux.c | 37 | ||||
-rw-r--r-- | drivers/pinctrl/pinmux.h | 1 |
3 files changed, 14 insertions, 27 deletions
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 7551611666f8..8164e7b4182b 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h | |||
@@ -53,8 +53,6 @@ struct pinctrl_dev { | |||
53 | * to keep track of nested use cases | 53 | * to keep track of nested use cases |
54 | * @pctldev: pin control device handling this pin control handle | 54 | * @pctldev: pin control device handling this pin control handle |
55 | * @mutex: a lock for the pin control state holder | 55 | * @mutex: a lock for the pin control state holder |
56 | * @func_selector: the function selector for the pinmux device handling | ||
57 | * this pinmux | ||
58 | * @groups: the group selectors for the pinmux device and | 56 | * @groups: the group selectors for the pinmux device and |
59 | * selector combination handling this pinmux, this is a list that | 57 | * selector combination handling this pinmux, this is a list that |
60 | * will be traversed on all pinmux operations such as | 58 | * will be traversed on all pinmux operations such as |
@@ -67,7 +65,6 @@ struct pinctrl { | |||
67 | struct pinctrl_dev *pctldev; | 65 | struct pinctrl_dev *pctldev; |
68 | struct mutex mutex; | 66 | struct mutex mutex; |
69 | #ifdef CONFIG_PINMUX | 67 | #ifdef CONFIG_PINMUX |
70 | unsigned func_selector; | ||
71 | struct list_head groups; | 68 | struct list_head groups; |
72 | #endif | 69 | #endif |
73 | }; | 70 | }; |
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 2a405618b448..f409f161ea1d 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c | |||
@@ -33,10 +33,13 @@ | |||
33 | /** | 33 | /** |
34 | * struct pinmux_group - group list item for pinmux groups | 34 | * struct pinmux_group - group list item for pinmux groups |
35 | * @node: pinmux group list node | 35 | * @node: pinmux group list node |
36 | * @func_selector: the function selector for the pinmux device handling | ||
37 | * this pinmux | ||
36 | * @group_selector: the group selector for this group | 38 | * @group_selector: the group selector for this group |
37 | */ | 39 | */ |
38 | struct pinmux_group { | 40 | struct pinmux_group { |
39 | struct list_head node; | 41 | struct list_head node; |
42 | unsigned func_selector; | ||
40 | unsigned group_selector; | 43 | unsigned group_selector; |
41 | }; | 44 | }; |
42 | 45 | ||
@@ -476,24 +479,11 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev, | |||
476 | if (ret < 0) | 479 | if (ret < 0) |
477 | return ret; | 480 | return ret; |
478 | 481 | ||
479 | /* | ||
480 | * If the function selector is already set, it needs to be identical, | ||
481 | * we support several groups with one function but not several | ||
482 | * functions with one or several groups in the same pinmux. | ||
483 | */ | ||
484 | if (p->func_selector != UINT_MAX && | ||
485 | p->func_selector != func_selector) { | ||
486 | dev_err(pctldev->dev, | ||
487 | "dual function defines in the map for device %s\n", | ||
488 | devname); | ||
489 | return -EINVAL; | ||
490 | } | ||
491 | p->func_selector = func_selector; | ||
492 | |||
493 | /* Now add this group selector, we may have many of them */ | 482 | /* Now add this group selector, we may have many of them */ |
494 | grp = kmalloc(sizeof(*grp), GFP_KERNEL); | 483 | grp = kmalloc(sizeof(*grp), GFP_KERNEL); |
495 | if (!grp) | 484 | if (!grp) |
496 | return -ENOMEM; | 485 | return -ENOMEM; |
486 | grp->func_selector = func_selector; | ||
497 | grp->group_selector = group_selector; | 487 | grp->group_selector = group_selector; |
498 | ret = acquire_pins(pctldev, devname, group_selector); | 488 | ret = acquire_pins(pctldev, devname, group_selector); |
499 | if (ret) { | 489 | if (ret) { |
@@ -554,7 +544,7 @@ int pinmux_enable(struct pinctrl *p) | |||
554 | int ret; | 544 | int ret; |
555 | 545 | ||
556 | list_for_each_entry(grp, &p->groups, node) { | 546 | list_for_each_entry(grp, &p->groups, node) { |
557 | ret = ops->enable(pctldev, p->func_selector, | 547 | ret = ops->enable(pctldev, grp->func_selector, |
558 | grp->group_selector); | 548 | grp->group_selector); |
559 | if (ret) | 549 | if (ret) |
560 | /* | 550 | /* |
@@ -576,7 +566,7 @@ void pinmux_disable(struct pinctrl *p) | |||
576 | struct pinmux_group *grp; | 566 | struct pinmux_group *grp; |
577 | 567 | ||
578 | list_for_each_entry(grp, &p->groups, node) { | 568 | list_for_each_entry(grp, &p->groups, node) { |
579 | ops->disable(pctldev, p->func_selector, | 569 | ops->disable(pctldev, grp->func_selector, |
580 | grp->group_selector); | 570 | grp->group_selector); |
581 | } | 571 | } |
582 | } | 572 | } |
@@ -654,21 +644,22 @@ void pinmux_dbg_show(struct seq_file *s, struct pinctrl *p) | |||
654 | const struct pinmux_ops *pmxops; | 644 | const struct pinmux_ops *pmxops; |
655 | const struct pinctrl_ops *pctlops; | 645 | const struct pinctrl_ops *pctlops; |
656 | struct pinmux_group *grp; | 646 | struct pinmux_group *grp; |
647 | const char *sep = ""; | ||
657 | 648 | ||
658 | pmxops = pctldev->desc->pmxops; | 649 | pmxops = pctldev->desc->pmxops; |
659 | pctlops = pctldev->desc->pctlops; | 650 | pctlops = pctldev->desc->pctlops; |
660 | 651 | ||
661 | seq_printf(s, " function: %s (%u),", | ||
662 | pmxops->get_function_name(pctldev, | ||
663 | p->func_selector), | ||
664 | p->func_selector); | ||
665 | |||
666 | seq_printf(s, " groups: ["); | 652 | seq_printf(s, " groups: ["); |
667 | list_for_each_entry(grp, &p->groups, node) { | 653 | list_for_each_entry(grp, &p->groups, node) { |
668 | seq_printf(s, " %s (%u)", | 654 | seq_printf(s, "%s%s (%u)=%s (%u)", |
655 | sep, | ||
669 | pctlops->get_group_name(pctldev, | 656 | pctlops->get_group_name(pctldev, |
670 | grp->group_selector), | 657 | grp->group_selector), |
671 | grp->group_selector); | 658 | grp->group_selector, |
659 | pmxops->get_function_name(pctldev, | ||
660 | grp->func_selector), | ||
661 | grp->func_selector); | ||
662 | sep = ", "; | ||
672 | } | 663 | } |
673 | seq_printf(s, " ]"); | 664 | seq_printf(s, " ]"); |
674 | } | 665 | } |
diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h index 84b8fe946b5c..822febb2d968 100644 --- a/drivers/pinctrl/pinmux.h +++ b/drivers/pinctrl/pinmux.h | |||
@@ -23,7 +23,6 @@ int pinmux_gpio_direction(struct pinctrl_dev *pctldev, | |||
23 | unsigned pin, bool input); | 23 | unsigned pin, bool input); |
24 | static inline void pinmux_init_pinctrl_handle(struct pinctrl *p) | 24 | static inline void pinmux_init_pinctrl_handle(struct pinctrl *p) |
25 | { | 25 | { |
26 | p->func_selector = UINT_MAX; | ||
27 | INIT_LIST_HEAD(&p->groups); | 26 | INIT_LIST_HEAD(&p->groups); |
28 | } | 27 | } |
29 | int pinmux_apply_muxmap(struct pinctrl_dev *pctldev, | 28 | int pinmux_apply_muxmap(struct pinctrl_dev *pctldev, |