diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-03-02 15:05:48 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-03-05 05:25:11 -0500 |
commit | 1e2082b520721734c358f776d34a069867214c8e (patch) | |
tree | 4d11e15a4127ad69faf7555864480a6fafe5422c /drivers/pinctrl | |
parent | 6e5e959dde0d92d177f035652aeaa77f9330c9c6 (diff) |
pinctrl: enhance mapping table to support pin config operations
The pinctrl mapping table can now contain entries to:
* Set the mux function of a pin group
* Apply a set of pin config options to a pin or a group
This allows pinctrl_select_state() to apply pin configs settings as well
as mux settings.
v3: Fix find_pinctrl() to iterate over the correct list.
s/_MUX_CONFIGS_/_CONFIGS_/ in mapping table macros.
Fix documentation to use correct mapping table macro.
v2: Added numerous extra PIN_MAP_*() special-case macros.
Fixed kerneldoc typo. Delete pinctrl_get_pin_id() and
replace it with pin_get_from_name(). Various minor fixes.
Updates due to rebase.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Dong Aisheng <dong.aisheng@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r-- | drivers/pinctrl/core.c | 154 | ||||
-rw-r--r-- | drivers/pinctrl/core.h | 35 | ||||
-rw-r--r-- | drivers/pinctrl/pinconf.c | 165 | ||||
-rw-r--r-- | drivers/pinctrl/pinconf.h | 40 | ||||
-rw-r--r-- | drivers/pinctrl/pinmux.c | 69 | ||||
-rw-r--r-- | drivers/pinctrl/pinmux.h | 23 |
6 files changed, 426 insertions, 60 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index c6f3ca32189e..ec3b8cc188af 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
@@ -502,6 +502,9 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map) | |||
502 | if (IS_ERR(state)) | 502 | if (IS_ERR(state)) |
503 | return PTR_ERR(state); | 503 | return PTR_ERR(state); |
504 | 504 | ||
505 | if (map->type == PIN_MAP_TYPE_DUMMY_STATE) | ||
506 | return 0; | ||
507 | |||
505 | setting = kzalloc(sizeof(*setting), GFP_KERNEL); | 508 | setting = kzalloc(sizeof(*setting), GFP_KERNEL); |
506 | if (setting == NULL) { | 509 | if (setting == NULL) { |
507 | dev_err(p->dev, | 510 | dev_err(p->dev, |
@@ -509,6 +512,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map) | |||
509 | return -ENOMEM; | 512 | return -ENOMEM; |
510 | } | 513 | } |
511 | 514 | ||
515 | setting->type = map->type; | ||
516 | |||
512 | setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name); | 517 | setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name); |
513 | if (setting->pctldev == NULL) { | 518 | if (setting->pctldev == NULL) { |
514 | dev_err(p->dev, "unknown pinctrl device %s in map entry", | 519 | dev_err(p->dev, "unknown pinctrl device %s in map entry", |
@@ -518,7 +523,18 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map) | |||
518 | return -ENODEV; | 523 | return -ENODEV; |
519 | } | 524 | } |
520 | 525 | ||
521 | ret = pinmux_map_to_setting(map, setting); | 526 | switch (map->type) { |
527 | case PIN_MAP_TYPE_MUX_GROUP: | ||
528 | ret = pinmux_map_to_setting(map, setting); | ||
529 | break; | ||
530 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
531 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
532 | ret = pinconf_map_to_setting(map, setting); | ||
533 | break; | ||
534 | default: | ||
535 | ret = -EINVAL; | ||
536 | break; | ||
537 | } | ||
522 | if (ret < 0) { | 538 | if (ret < 0) { |
523 | kfree(setting); | 539 | kfree(setting); |
524 | return ret; | 540 | return ret; |
@@ -533,7 +549,7 @@ static struct pinctrl *find_pinctrl(struct device *dev) | |||
533 | { | 549 | { |
534 | struct pinctrl *p; | 550 | struct pinctrl *p; |
535 | 551 | ||
536 | list_for_each_entry(p, &pinctrldev_list, node) | 552 | list_for_each_entry(p, &pinctrl_list, node) |
537 | if (p->dev == dev) | 553 | if (p->dev == dev) |
538 | return p; | 554 | return p; |
539 | 555 | ||
@@ -626,9 +642,19 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist) | |||
626 | 642 | ||
627 | list_for_each_entry_safe(state, n1, &p->states, node) { | 643 | list_for_each_entry_safe(state, n1, &p->states, node) { |
628 | list_for_each_entry_safe(setting, n2, &state->settings, node) { | 644 | list_for_each_entry_safe(setting, n2, &state->settings, node) { |
629 | if (state == p->state) | 645 | switch (setting->type) { |
630 | pinmux_disable_setting(setting); | 646 | case PIN_MAP_TYPE_MUX_GROUP: |
631 | pinmux_free_setting(setting); | 647 | if (state == p->state) |
648 | pinmux_disable_setting(setting); | ||
649 | pinmux_free_setting(setting); | ||
650 | break; | ||
651 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
652 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
653 | pinconf_free_setting(setting); | ||
654 | break; | ||
655 | default: | ||
656 | break; | ||
657 | } | ||
632 | list_del(&setting->node); | 658 | list_del(&setting->node); |
633 | kfree(setting); | 659 | kfree(setting); |
634 | } | 660 | } |
@@ -703,9 +729,13 @@ static int pinctrl_select_state_locked(struct pinctrl *p, | |||
703 | */ | 729 | */ |
704 | list_for_each_entry(setting, &p->state->settings, node) { | 730 | list_for_each_entry(setting, &p->state->settings, node) { |
705 | bool found = false; | 731 | bool found = false; |
732 | if (setting->type != PIN_MAP_TYPE_MUX_GROUP) | ||
733 | continue; | ||
706 | list_for_each_entry(setting2, &state->settings, node) { | 734 | list_for_each_entry(setting2, &state->settings, node) { |
707 | if (setting2->group_selector == | 735 | if (setting2->type != PIN_MAP_TYPE_MUX_GROUP) |
708 | setting->group_selector) { | 736 | continue; |
737 | if (setting2->data.mux.group == | ||
738 | setting->data.mux.group) { | ||
709 | found = true; | 739 | found = true; |
710 | break; | 740 | break; |
711 | } | 741 | } |
@@ -719,7 +749,18 @@ static int pinctrl_select_state_locked(struct pinctrl *p, | |||
719 | 749 | ||
720 | /* Apply all the settings for the new state */ | 750 | /* Apply all the settings for the new state */ |
721 | list_for_each_entry(setting, &state->settings, node) { | 751 | list_for_each_entry(setting, &state->settings, node) { |
722 | ret = pinmux_enable_setting(setting); | 752 | switch (setting->type) { |
753 | case PIN_MAP_TYPE_MUX_GROUP: | ||
754 | ret = pinmux_enable_setting(setting); | ||
755 | break; | ||
756 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
757 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
758 | ret = pinconf_apply_setting(setting); | ||
759 | break; | ||
760 | default: | ||
761 | ret = -EINVAL; | ||
762 | break; | ||
763 | } | ||
723 | if (ret < 0) { | 764 | if (ret < 0) { |
724 | /* FIXME: Difficult to return to prev state */ | 765 | /* FIXME: Difficult to return to prev state */ |
725 | return ret; | 766 | return ret; |
@@ -756,33 +797,48 @@ EXPORT_SYMBOL_GPL(pinctrl_select_state); | |||
756 | int pinctrl_register_mappings(struct pinctrl_map const *maps, | 797 | int pinctrl_register_mappings(struct pinctrl_map const *maps, |
757 | unsigned num_maps) | 798 | unsigned num_maps) |
758 | { | 799 | { |
759 | int i; | 800 | int i, ret; |
760 | struct pinctrl_maps *maps_node; | 801 | struct pinctrl_maps *maps_node; |
761 | 802 | ||
762 | pr_debug("add %d pinmux maps\n", num_maps); | 803 | pr_debug("add %d pinmux maps\n", num_maps); |
763 | 804 | ||
764 | /* First sanity check the new mapping */ | 805 | /* First sanity check the new mapping */ |
765 | for (i = 0; i < num_maps; i++) { | 806 | for (i = 0; i < num_maps; i++) { |
807 | if (!maps[i].dev_name) { | ||
808 | pr_err("failed to register map %s (%d): no device given\n", | ||
809 | maps[i].name, i); | ||
810 | return -EINVAL; | ||
811 | } | ||
812 | |||
766 | if (!maps[i].name) { | 813 | if (!maps[i].name) { |
767 | pr_err("failed to register map %d: no map name given\n", | 814 | pr_err("failed to register map %d: no map name given\n", |
768 | i); | 815 | i); |
769 | return -EINVAL; | 816 | return -EINVAL; |
770 | } | 817 | } |
771 | 818 | ||
772 | if (!maps[i].ctrl_dev_name) { | 819 | if (maps[i].type != PIN_MAP_TYPE_DUMMY_STATE && |
820 | !maps[i].ctrl_dev_name) { | ||
773 | pr_err("failed to register map %s (%d): no pin control device given\n", | 821 | pr_err("failed to register map %s (%d): no pin control device given\n", |
774 | maps[i].name, i); | 822 | maps[i].name, i); |
775 | return -EINVAL; | 823 | return -EINVAL; |
776 | } | 824 | } |
777 | 825 | ||
778 | if (!maps[i].function) { | 826 | switch (maps[i].type) { |
779 | pr_err("failed to register map %s (%d): no function ID given\n", | 827 | case PIN_MAP_TYPE_DUMMY_STATE: |
780 | maps[i].name, i); | 828 | break; |
781 | return -EINVAL; | 829 | case PIN_MAP_TYPE_MUX_GROUP: |
782 | } | 830 | ret = pinmux_validate_map(&maps[i], i); |
783 | 831 | if (ret < 0) | |
784 | if (!maps[i].dev_name) { | 832 | return 0; |
785 | pr_err("failed to register map %s (%d): no device given\n", | 833 | break; |
834 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
835 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
836 | ret = pinconf_validate_map(&maps[i], i); | ||
837 | if (ret < 0) | ||
838 | return 0; | ||
839 | break; | ||
840 | default: | ||
841 | pr_err("failed to register map %s (%d): invalid type given\n", | ||
786 | maps[i].name, i); | 842 | maps[i].name, i); |
787 | return -EINVAL; | 843 | return -EINVAL; |
788 | } | 844 | } |
@@ -934,6 +990,22 @@ static int pinctrl_devices_show(struct seq_file *s, void *what) | |||
934 | return 0; | 990 | return 0; |
935 | } | 991 | } |
936 | 992 | ||
993 | static inline const char *map_type(enum pinctrl_map_type type) | ||
994 | { | ||
995 | static const char * const names[] = { | ||
996 | "INVALID", | ||
997 | "DUMMY_STATE", | ||
998 | "MUX_GROUP", | ||
999 | "CONFIGS_PIN", | ||
1000 | "CONFIGS_GROUP", | ||
1001 | }; | ||
1002 | |||
1003 | if (type >= ARRAY_SIZE(names)) | ||
1004 | return "UNKNOWN"; | ||
1005 | |||
1006 | return names[type]; | ||
1007 | } | ||
1008 | |||
937 | static int pinctrl_maps_show(struct seq_file *s, void *what) | 1009 | static int pinctrl_maps_show(struct seq_file *s, void *what) |
938 | { | 1010 | { |
939 | struct pinctrl_maps *maps_node; | 1011 | struct pinctrl_maps *maps_node; |
@@ -945,12 +1017,27 @@ static int pinctrl_maps_show(struct seq_file *s, void *what) | |||
945 | mutex_lock(&pinctrl_mutex); | 1017 | mutex_lock(&pinctrl_mutex); |
946 | 1018 | ||
947 | for_each_maps(maps_node, i, map) { | 1019 | for_each_maps(maps_node, i, map) { |
948 | seq_printf(s, "%s:\n", map->name); | 1020 | seq_printf(s, "device %s\nstate %s\ntype %s (%d)\n", |
949 | seq_printf(s, " device: %s\n", map->dev_name); | 1021 | map->dev_name, map->name, map_type(map->type), |
950 | seq_printf(s, " controlling device %s\n", map->ctrl_dev_name); | 1022 | map->type); |
951 | seq_printf(s, " function: %s\n", map->function); | 1023 | |
952 | seq_printf(s, " group: %s\n", map->group ? map->group : | 1024 | if (map->type != PIN_MAP_TYPE_DUMMY_STATE) |
953 | "(default)"); | 1025 | seq_printf(s, "controlling device %s\n", |
1026 | map->ctrl_dev_name); | ||
1027 | |||
1028 | switch (map->type) { | ||
1029 | case PIN_MAP_TYPE_MUX_GROUP: | ||
1030 | pinmux_show_map(s, map); | ||
1031 | break; | ||
1032 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
1033 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
1034 | pinconf_show_map(s, map); | ||
1035 | break; | ||
1036 | default: | ||
1037 | break; | ||
1038 | } | ||
1039 | |||
1040 | seq_printf(s, "\n"); | ||
954 | } | 1041 | } |
955 | 1042 | ||
956 | mutex_unlock(&pinctrl_mutex); | 1043 | mutex_unlock(&pinctrl_mutex); |
@@ -977,8 +1064,23 @@ static int pinctrl_show(struct seq_file *s, void *what) | |||
977 | seq_printf(s, " state: %s\n", state->name); | 1064 | seq_printf(s, " state: %s\n", state->name); |
978 | 1065 | ||
979 | list_for_each_entry(setting, &state->settings, node) { | 1066 | list_for_each_entry(setting, &state->settings, node) { |
980 | seq_printf(s, " "); | 1067 | struct pinctrl_dev *pctldev = setting->pctldev; |
981 | pinmux_dbg_show(s, setting); | 1068 | |
1069 | seq_printf(s, " type: %s controller %s ", | ||
1070 | map_type(setting->type), | ||
1071 | pinctrl_dev_get_name(pctldev)); | ||
1072 | |||
1073 | switch (setting->type) { | ||
1074 | case PIN_MAP_TYPE_MUX_GROUP: | ||
1075 | pinmux_show_setting(s, setting); | ||
1076 | break; | ||
1077 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
1078 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
1079 | pinconf_show_setting(s, setting); | ||
1080 | break; | ||
1081 | default: | ||
1082 | break; | ||
1083 | } | ||
982 | } | 1084 | } |
983 | } | 1085 | } |
984 | } | 1086 | } |
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 5691d312e15a..1cae3723bbed 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h | |||
@@ -72,17 +72,44 @@ struct pinctrl_state { | |||
72 | }; | 72 | }; |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * struct pinctrl_setting_mux - setting data for MAP_TYPE_MUX_GROUP | ||
76 | * @group: the group selector to program | ||
77 | * @func: the function selector to program | ||
78 | */ | ||
79 | struct pinctrl_setting_mux { | ||
80 | unsigned group; | ||
81 | unsigned func; | ||
82 | }; | ||
83 | |||
84 | /** | ||
85 | * struct pinctrl_setting_configs - setting data for MAP_TYPE_CONFIGS_* | ||
86 | * @group_or_pin: the group selector or pin ID to program | ||
87 | * @configs: a pointer to an array of config parameters/values to program into | ||
88 | * hardware. Each individual pin controller defines the format and meaning | ||
89 | * of config parameters. | ||
90 | * @num_configs: the number of entries in array @configs | ||
91 | */ | ||
92 | struct pinctrl_setting_configs { | ||
93 | unsigned group_or_pin; | ||
94 | unsigned long *configs; | ||
95 | unsigned num_configs; | ||
96 | }; | ||
97 | |||
98 | /** | ||
75 | * struct pinctrl_setting - an individual mux setting | 99 | * struct pinctrl_setting - an individual mux setting |
76 | * @node: list node for struct pinctrl_settings's @settings field | 100 | * @node: list node for struct pinctrl_settings's @settings field |
101 | * @type: the type of setting | ||
77 | * @pctldev: pin control device handling to be programmed | 102 | * @pctldev: pin control device handling to be programmed |
78 | * @group_selector: the group selector to program | 103 | * @data: Data specific to the setting type |
79 | * @func_selector: the function selector to program | ||
80 | */ | 104 | */ |
81 | struct pinctrl_setting { | 105 | struct pinctrl_setting { |
82 | struct list_head node; | 106 | struct list_head node; |
107 | enum pinctrl_map_type type; | ||
83 | struct pinctrl_dev *pctldev; | 108 | struct pinctrl_dev *pctldev; |
84 | unsigned group_selector; | 109 | union { |
85 | unsigned func_selector; | 110 | struct pinctrl_setting_mux mux; |
111 | struct pinctrl_setting_configs configs; | ||
112 | } data; | ||
86 | }; | 113 | }; |
87 | 114 | ||
88 | /** | 115 | /** |
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index e0a453790a40..84869f28b101 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c | |||
@@ -36,6 +36,24 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev) | |||
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | 38 | ||
39 | int pinconf_validate_map(struct pinctrl_map const *map, int i) | ||
40 | { | ||
41 | if (!map->data.configs.group_or_pin) { | ||
42 | pr_err("failed to register map %s (%d): no group/pin given\n", | ||
43 | map->name, i); | ||
44 | return -EINVAL; | ||
45 | } | ||
46 | |||
47 | if (map->data.configs.num_configs && | ||
48 | !map->data.configs.configs) { | ||
49 | pr_err("failed to register map %s (%d): no configs ptr given\n", | ||
50 | map->name, i); | ||
51 | return -EINVAL; | ||
52 | } | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
39 | static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, | 57 | static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, |
40 | unsigned long *config) | 58 | unsigned long *config) |
41 | { | 59 | { |
@@ -260,8 +278,155 @@ unlock: | |||
260 | } | 278 | } |
261 | EXPORT_SYMBOL(pin_config_group_set); | 279 | EXPORT_SYMBOL(pin_config_group_set); |
262 | 280 | ||
281 | int pinconf_map_to_setting(struct pinctrl_map const *map, | ||
282 | struct pinctrl_setting *setting) | ||
283 | { | ||
284 | struct pinctrl_dev *pctldev = setting->pctldev; | ||
285 | |||
286 | switch (setting->type) { | ||
287 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
288 | setting->data.configs.group_or_pin = | ||
289 | pin_get_from_name(pctldev, | ||
290 | map->data.configs.group_or_pin); | ||
291 | if (setting->data.configs.group_or_pin < 0) | ||
292 | return setting->data.configs.group_or_pin; | ||
293 | break; | ||
294 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
295 | setting->data.configs.group_or_pin = | ||
296 | pinctrl_get_group_selector(pctldev, | ||
297 | map->data.configs.group_or_pin); | ||
298 | if (setting->data.configs.group_or_pin < 0) | ||
299 | return setting->data.configs.group_or_pin; | ||
300 | break; | ||
301 | default: | ||
302 | return -EINVAL; | ||
303 | } | ||
304 | |||
305 | setting->data.configs.num_configs = map->data.configs.num_configs; | ||
306 | setting->data.configs.configs = map->data.configs.configs; | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | void pinconf_free_setting(struct pinctrl_setting const *setting) | ||
312 | { | ||
313 | } | ||
314 | |||
315 | int pinconf_apply_setting(struct pinctrl_setting const *setting) | ||
316 | { | ||
317 | struct pinctrl_dev *pctldev = setting->pctldev; | ||
318 | const struct pinconf_ops *ops = pctldev->desc->confops; | ||
319 | int i, ret; | ||
320 | |||
321 | if (!ops) { | ||
322 | dev_err(pctldev->dev, "missing confops\n"); | ||
323 | return -EINVAL; | ||
324 | } | ||
325 | |||
326 | switch (setting->type) { | ||
327 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
328 | if (!ops->pin_config_set) { | ||
329 | dev_err(pctldev->dev, "missing pin_config_set op\n"); | ||
330 | return -EINVAL; | ||
331 | } | ||
332 | for (i = 0; i < setting->data.configs.num_configs; i++) { | ||
333 | ret = ops->pin_config_set(pctldev, | ||
334 | setting->data.configs.group_or_pin, | ||
335 | setting->data.configs.configs[i]); | ||
336 | if (ret < 0) { | ||
337 | dev_err(pctldev->dev, | ||
338 | "pin_config_set op failed for pin %d config %08lx\n", | ||
339 | setting->data.configs.group_or_pin, | ||
340 | setting->data.configs.configs[i]); | ||
341 | return ret; | ||
342 | } | ||
343 | } | ||
344 | break; | ||
345 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
346 | if (!ops->pin_config_group_set) { | ||
347 | dev_err(pctldev->dev, | ||
348 | "missing pin_config_group_set op\n"); | ||
349 | return -EINVAL; | ||
350 | } | ||
351 | for (i = 0; i < setting->data.configs.num_configs; i++) { | ||
352 | ret = ops->pin_config_group_set(pctldev, | ||
353 | setting->data.configs.group_or_pin, | ||
354 | setting->data.configs.configs[i]); | ||
355 | if (ret < 0) { | ||
356 | dev_err(pctldev->dev, | ||
357 | "pin_config_group_set op failed for group %d config %08lx\n", | ||
358 | setting->data.configs.group_or_pin, | ||
359 | setting->data.configs.configs[i]); | ||
360 | return ret; | ||
361 | } | ||
362 | } | ||
363 | break; | ||
364 | default: | ||
365 | return -EINVAL; | ||
366 | } | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
263 | #ifdef CONFIG_DEBUG_FS | 371 | #ifdef CONFIG_DEBUG_FS |
264 | 372 | ||
373 | void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map) | ||
374 | { | ||
375 | int i; | ||
376 | |||
377 | switch (map->type) { | ||
378 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
379 | seq_printf(s, "pin "); | ||
380 | break; | ||
381 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
382 | seq_printf(s, "group "); | ||
383 | break; | ||
384 | default: | ||
385 | break; | ||
386 | } | ||
387 | |||
388 | seq_printf(s, "%s\n", map->data.configs.group_or_pin); | ||
389 | |||
390 | for (i = 0; i < map->data.configs.num_configs; i++) | ||
391 | seq_printf(s, "config %08lx\n", map->data.configs.configs[i]); | ||
392 | } | ||
393 | |||
394 | void pinconf_show_setting(struct seq_file *s, | ||
395 | struct pinctrl_setting const *setting) | ||
396 | { | ||
397 | struct pinctrl_dev *pctldev = setting->pctldev; | ||
398 | const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; | ||
399 | struct pin_desc *desc; | ||
400 | int i; | ||
401 | |||
402 | switch (setting->type) { | ||
403 | case PIN_MAP_TYPE_CONFIGS_PIN: | ||
404 | desc = pin_desc_get(setting->pctldev, | ||
405 | setting->data.configs.group_or_pin); | ||
406 | seq_printf(s, "pin %s (%d)", | ||
407 | desc->name ? desc->name : "unnamed", | ||
408 | setting->data.configs.group_or_pin); | ||
409 | break; | ||
410 | case PIN_MAP_TYPE_CONFIGS_GROUP: | ||
411 | seq_printf(s, "group %s (%d)", | ||
412 | pctlops->get_group_name(pctldev, | ||
413 | setting->data.configs.group_or_pin), | ||
414 | setting->data.configs.group_or_pin); | ||
415 | break; | ||
416 | default: | ||
417 | break; | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * FIXME: We should really get the pin controler to dump the config | ||
422 | * values, so they can be decoded to something meaningful. | ||
423 | */ | ||
424 | for (i = 0; i < setting->data.configs.num_configs; i++) | ||
425 | seq_printf(s, " %08lx", setting->data.configs.configs[i]); | ||
426 | |||
427 | seq_printf(s, "\n"); | ||
428 | } | ||
429 | |||
265 | static void pinconf_dump_pin(struct pinctrl_dev *pctldev, | 430 | static void pinconf_dump_pin(struct pinctrl_dev *pctldev, |
266 | struct seq_file *s, int pin) | 431 | struct seq_file *s, int pin) |
267 | { | 432 | { |
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h index 1d6ea9de75fc..0ded227661a5 100644 --- a/drivers/pinctrl/pinconf.h +++ b/drivers/pinctrl/pinconf.h | |||
@@ -15,6 +15,16 @@ | |||
15 | 15 | ||
16 | int pinconf_check_ops(struct pinctrl_dev *pctldev); | 16 | int pinconf_check_ops(struct pinctrl_dev *pctldev); |
17 | 17 | ||
18 | int pinconf_validate_map(struct pinctrl_map const *map, int i); | ||
19 | |||
20 | int pinconf_map_to_setting(struct pinctrl_map const *map, | ||
21 | struct pinctrl_setting *setting); | ||
22 | void pinconf_free_setting(struct pinctrl_setting const *setting); | ||
23 | int pinconf_apply_setting(struct pinctrl_setting const *setting); | ||
24 | |||
25 | void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map); | ||
26 | void pinconf_show_setting(struct seq_file *s, | ||
27 | struct pinctrl_setting const *setting); | ||
18 | void pinconf_init_device_debugfs(struct dentry *devroot, | 28 | void pinconf_init_device_debugfs(struct dentry *devroot, |
19 | struct pinctrl_dev *pctldev); | 29 | struct pinctrl_dev *pctldev); |
20 | 30 | ||
@@ -25,6 +35,36 @@ static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) | |||
25 | return 0; | 35 | return 0; |
26 | } | 36 | } |
27 | 37 | ||
38 | static inline int pinconf_validate_map(struct pinctrl_map const *map, int i) | ||
39 | { | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | static inline int pinconf_map_to_setting(struct pinctrl_map const *map, | ||
44 | struct pinctrl_setting *setting) | ||
45 | { | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static inline void pinconf_free_setting(struct pinctrl_setting const *setting) | ||
50 | { | ||
51 | } | ||
52 | |||
53 | static inline int pinconf_apply_setting(struct pinctrl_setting const *setting) | ||
54 | { | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static inline void pinconf_show_map(struct seq_file *s, | ||
59 | struct pinctrl_map const *map) | ||
60 | { | ||
61 | } | ||
62 | |||
63 | static inline void pinconf_show_setting(struct seq_file *s, | ||
64 | struct pinctrl_setting const *setting) | ||
65 | { | ||
66 | } | ||
67 | |||
28 | static inline void pinconf_init_device_debugfs(struct dentry *devroot, | 68 | static inline void pinconf_init_device_debugfs(struct dentry *devroot, |
29 | struct pinctrl_dev *pctldev) | 69 | struct pinctrl_dev *pctldev) |
30 | { | 70 | { |
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 56ca42e6a6ec..4852ebe5712e 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c | |||
@@ -58,6 +58,17 @@ int pinmux_check_ops(struct pinctrl_dev *pctldev) | |||
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | int pinmux_validate_map(struct pinctrl_map const *map, int i) | ||
62 | { | ||
63 | if (!map->data.mux.function) { | ||
64 | pr_err("failed to register map %s (%d): no function given\n", | ||
65 | map->name, i); | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
61 | /** | 72 | /** |
62 | * pin_request() - request a single pin to be muxed in, typically for GPIO | 73 | * pin_request() - request a single pin to be muxed in, typically for GPIO |
63 | * @pin: the pin number in the global pin space | 74 | * @pin: the pin number in the global pin space |
@@ -284,21 +295,21 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, | |||
284 | const unsigned *pins; | 295 | const unsigned *pins; |
285 | unsigned num_pins; | 296 | unsigned num_pins; |
286 | 297 | ||
287 | setting->func_selector = | 298 | setting->data.mux.func = |
288 | pinmux_func_name_to_selector(pctldev, map->function); | 299 | pinmux_func_name_to_selector(pctldev, map->data.mux.function); |
289 | if (setting->func_selector < 0) | 300 | if (setting->data.mux.func < 0) |
290 | return setting->func_selector; | 301 | return setting->data.mux.func; |
291 | 302 | ||
292 | ret = pmxops->get_function_groups(pctldev, setting->func_selector, | 303 | ret = pmxops->get_function_groups(pctldev, setting->data.mux.func, |
293 | &groups, &num_groups); | 304 | &groups, &num_groups); |
294 | if (ret < 0) | 305 | if (ret < 0) |
295 | return ret; | 306 | return ret; |
296 | if (!num_groups) | 307 | if (!num_groups) |
297 | return -EINVAL; | 308 | return -EINVAL; |
298 | 309 | ||
299 | if (map->group) { | 310 | if (map->data.mux.group) { |
300 | bool found = false; | 311 | bool found = false; |
301 | group = map->group; | 312 | group = map->data.mux.group; |
302 | for (i = 0; i < num_groups; i++) { | 313 | for (i = 0; i < num_groups; i++) { |
303 | if (!strcmp(group, groups[i])) { | 314 | if (!strcmp(group, groups[i])) { |
304 | found = true; | 315 | found = true; |
@@ -311,17 +322,16 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, | |||
311 | group = groups[0]; | 322 | group = groups[0]; |
312 | } | 323 | } |
313 | 324 | ||
314 | setting->group_selector = | 325 | setting->data.mux.group = pinctrl_get_group_selector(pctldev, group); |
315 | pinctrl_get_group_selector(pctldev, group); | 326 | if (setting->data.mux.group < 0) |
316 | if (setting->group_selector < 0) | 327 | return setting->data.mux.group; |
317 | return setting->group_selector; | ||
318 | 328 | ||
319 | ret = pctlops->get_group_pins(pctldev, setting->group_selector, | 329 | ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins, |
320 | &pins, &num_pins); | 330 | &num_pins); |
321 | if (ret) { | 331 | if (ret) { |
322 | dev_err(pctldev->dev, | 332 | dev_err(pctldev->dev, |
323 | "could not get pins for device %s group selector %d\n", | 333 | "could not get pins for device %s group selector %d\n", |
324 | pinctrl_dev_get_name(pctldev), setting->group_selector); | 334 | pinctrl_dev_get_name(pctldev), setting->data.mux.group); |
325 | return -ENODEV; | 335 | return -ENODEV; |
326 | } | 336 | } |
327 | 337 | ||
@@ -352,12 +362,12 @@ void pinmux_free_setting(struct pinctrl_setting const *setting) | |||
352 | int ret; | 362 | int ret; |
353 | int i; | 363 | int i; |
354 | 364 | ||
355 | ret = pctlops->get_group_pins(pctldev, setting->group_selector, | 365 | ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, |
356 | &pins, &num_pins); | 366 | &pins, &num_pins); |
357 | if (ret) { | 367 | if (ret) { |
358 | dev_err(pctldev->dev, | 368 | dev_err(pctldev->dev, |
359 | "could not get pins for device %s group selector %d\n", | 369 | "could not get pins for device %s group selector %d\n", |
360 | pinctrl_dev_get_name(pctldev), setting->group_selector); | 370 | pinctrl_dev_get_name(pctldev), setting->data.mux.group); |
361 | return; | 371 | return; |
362 | } | 372 | } |
363 | 373 | ||
@@ -370,8 +380,8 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting) | |||
370 | struct pinctrl_dev *pctldev = setting->pctldev; | 380 | struct pinctrl_dev *pctldev = setting->pctldev; |
371 | const struct pinmux_ops *ops = pctldev->desc->pmxops; | 381 | const struct pinmux_ops *ops = pctldev->desc->pmxops; |
372 | 382 | ||
373 | return ops->enable(pctldev, setting->func_selector, | 383 | return ops->enable(pctldev, setting->data.mux.func, |
374 | setting->group_selector); | 384 | setting->data.mux.group); |
375 | } | 385 | } |
376 | 386 | ||
377 | void pinmux_disable_setting(struct pinctrl_setting const *setting) | 387 | void pinmux_disable_setting(struct pinctrl_setting const *setting) |
@@ -379,7 +389,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting) | |||
379 | struct pinctrl_dev *pctldev = setting->pctldev; | 389 | struct pinctrl_dev *pctldev = setting->pctldev; |
380 | const struct pinmux_ops *ops = pctldev->desc->pmxops; | 390 | const struct pinmux_ops *ops = pctldev->desc->pmxops; |
381 | 391 | ||
382 | ops->disable(pctldev, setting->func_selector, setting->group_selector); | 392 | ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group); |
383 | } | 393 | } |
384 | 394 | ||
385 | #ifdef CONFIG_DEBUG_FS | 395 | #ifdef CONFIG_DEBUG_FS |
@@ -456,18 +466,25 @@ static int pinmux_pins_show(struct seq_file *s, void *what) | |||
456 | return 0; | 466 | return 0; |
457 | } | 467 | } |
458 | 468 | ||
459 | void pinmux_dbg_show(struct seq_file *s, struct pinctrl_setting const *setting) | 469 | void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map) |
470 | { | ||
471 | seq_printf(s, "group %s\nfunction %s\n", | ||
472 | map->data.mux.group ? map->data.mux.group : "(default)", | ||
473 | map->data.mux.function); | ||
474 | } | ||
475 | |||
476 | void pinmux_show_setting(struct seq_file *s, | ||
477 | struct pinctrl_setting const *setting) | ||
460 | { | 478 | { |
461 | struct pinctrl_dev *pctldev = setting->pctldev; | 479 | struct pinctrl_dev *pctldev = setting->pctldev; |
462 | const struct pinmux_ops *pmxops = pctldev->desc->pmxops; | 480 | const struct pinmux_ops *pmxops = pctldev->desc->pmxops; |
463 | const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; | 481 | const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; |
464 | 482 | ||
465 | seq_printf(s, "controller: %s group: %s (%u) function: %s (%u)\n", | 483 | seq_printf(s, "group: %s (%u) function: %s (%u)\n", |
466 | pinctrl_dev_get_name(pctldev), | 484 | pctlops->get_group_name(pctldev, setting->data.mux.group), |
467 | pctlops->get_group_name(pctldev, setting->group_selector), | 485 | setting->data.mux.group, |
468 | setting->group_selector, | 486 | pmxops->get_function_name(pctldev, setting->data.mux.func), |
469 | pmxops->get_function_name(pctldev, setting->func_selector), | 487 | setting->data.mux.func); |
470 | setting->func_selector); | ||
471 | } | 488 | } |
472 | 489 | ||
473 | static int pinmux_functions_open(struct inode *inode, struct file *file) | 490 | static int pinmux_functions_open(struct inode *inode, struct file *file) |
diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h index 1500ae88f87c..6fc47003e95d 100644 --- a/drivers/pinctrl/pinmux.h +++ b/drivers/pinctrl/pinmux.h | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | int pinmux_check_ops(struct pinctrl_dev *pctldev); | 15 | int pinmux_check_ops(struct pinctrl_dev *pctldev); |
16 | 16 | ||
17 | int pinmux_validate_map(struct pinctrl_map const *map, int i); | ||
18 | |||
17 | int pinmux_request_gpio(struct pinctrl_dev *pctldev, | 19 | int pinmux_request_gpio(struct pinctrl_dev *pctldev, |
18 | struct pinctrl_gpio_range *range, | 20 | struct pinctrl_gpio_range *range, |
19 | unsigned pin, unsigned gpio); | 21 | unsigned pin, unsigned gpio); |
@@ -29,7 +31,9 @@ void pinmux_free_setting(struct pinctrl_setting const *setting); | |||
29 | int pinmux_enable_setting(struct pinctrl_setting const *setting); | 31 | int pinmux_enable_setting(struct pinctrl_setting const *setting); |
30 | void pinmux_disable_setting(struct pinctrl_setting const *setting); | 32 | void pinmux_disable_setting(struct pinctrl_setting const *setting); |
31 | 33 | ||
32 | void pinmux_dbg_show(struct seq_file *s, struct pinctrl_setting const *setting); | 34 | void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map); |
35 | void pinmux_show_setting(struct seq_file *s, | ||
36 | struct pinctrl_setting const *setting); | ||
33 | void pinmux_init_device_debugfs(struct dentry *devroot, | 37 | void pinmux_init_device_debugfs(struct dentry *devroot, |
34 | struct pinctrl_dev *pctldev); | 38 | struct pinctrl_dev *pctldev); |
35 | 39 | ||
@@ -40,6 +44,11 @@ static inline int pinmux_check_ops(struct pinctrl_dev *pctldev) | |||
40 | return 0; | 44 | return 0; |
41 | } | 45 | } |
42 | 46 | ||
47 | static inline int pinmux_validate_map(struct pinctrl_map const *map, int i) | ||
48 | { | ||
49 | return 0; | ||
50 | } | ||
51 | |||
43 | static inline int pinmux_request_gpio(struct pinctrl_dev *pctldev, | 52 | static inline int pinmux_request_gpio(struct pinctrl_dev *pctldev, |
44 | struct pinctrl_gpio_range *range, | 53 | struct pinctrl_gpio_range *range, |
45 | unsigned pin, unsigned gpio) | 54 | unsigned pin, unsigned gpio) |
@@ -80,12 +89,18 @@ static inline void pinmux_disable_setting( | |||
80 | { | 89 | { |
81 | } | 90 | } |
82 | 91 | ||
83 | static inline void pinmux_init_device_debugfs(struct dentry *devroot, | 92 | static inline void pinmux_show_map(struct seq_file *s, |
84 | struct pinctrl_dev *pctldev) | 93 | struct pinctrl_map const *map) |
94 | { | ||
95 | } | ||
96 | |||
97 | static inline void pinmux_show_setting(struct seq_file *s, | ||
98 | struct pinctrl_setting const *setting) | ||
85 | { | 99 | { |
86 | } | 100 | } |
87 | 101 | ||
88 | static inline void pinmux_dbg_show(struct seq_file *s, struct pinctrl *p) | 102 | static inline void pinmux_init_device_debugfs(struct dentry *devroot, |
103 | struct pinctrl_dev *pctldev) | ||
89 | { | 104 | { |
90 | } | 105 | } |
91 | 106 | ||