diff options
author | Stephen Warren <swarren@nvidia.com> | 2012-03-02 15:05:47 -0500 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-03-05 05:22:59 -0500 |
commit | 6e5e959dde0d92d177f035652aeaa77f9330c9c6 (patch) | |
tree | c2d874df6a1c591b558a17591a1c8fbc2ba7a1e1 /drivers/pinctrl | |
parent | 0e3db173e2b9fd3b82246516e72c17763eb5f98d (diff) |
pinctrl: API changes to support multiple states per device
The API model is changed from:
p = pinctrl_get(dev, "state1");
pinctrl_enable(p);
...
pinctrl_disable(p);
pinctrl_put(p);
p = pinctrl_get(dev, "state2");
pinctrl_enable(p);
...
pinctrl_disable(p);
pinctrl_put(p);
to this:
p = pinctrl_get(dev);
s1 = pinctrl_lookup_state(p, "state1");
s2 = pinctrl_lookup_state(p, "state2");
pinctrl_select_state(p, s1);
...
pinctrl_select_state(p, s2);
...
pinctrl_put(p);
This allows devices to directly transition between states without
disabling the pin controller programming and put()/get()ing the
configuration data each time. This model will also better suit pinconf
programming, which doesn't have a concept of "disable".
The special-case hogging feature of pin controllers is re-written to use
the regular APIs instead of special-case code. Hence, the pinmux-hogs
debugfs file is removed; see the top-level pinctrl-handles files for
equivalent data.
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 | 363 | ||||
-rw-r--r-- | drivers/pinctrl/core.h | 23 |
2 files changed, 237 insertions, 149 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 535f8d53c289..c6f3ca32189e 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c | |||
@@ -458,25 +458,98 @@ int pinctrl_gpio_direction_output(unsigned gpio) | |||
458 | } | 458 | } |
459 | EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output); | 459 | EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output); |
460 | 460 | ||
461 | static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name) | 461 | static struct pinctrl_state *find_state(struct pinctrl *p, |
462 | const char *name) | ||
462 | { | 463 | { |
463 | struct pinctrl_dev *pctldev; | 464 | struct pinctrl_state *state; |
464 | const char *devname; | 465 | |
465 | struct pinctrl *p; | 466 | list_for_each_entry(state, &p->states, node) |
466 | unsigned num_maps = 0; | 467 | if (!strcmp(state->name, name)) |
467 | int ret; | 468 | return state; |
468 | struct pinctrl_maps *maps_node; | 469 | |
469 | int i; | 470 | return NULL; |
470 | struct pinctrl_map const *map; | 471 | } |
472 | |||
473 | static struct pinctrl_state *create_state(struct pinctrl *p, | ||
474 | const char *name) | ||
475 | { | ||
476 | struct pinctrl_state *state; | ||
477 | |||
478 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
479 | if (state == NULL) { | ||
480 | dev_err(p->dev, | ||
481 | "failed to alloc struct pinctrl_state\n"); | ||
482 | return ERR_PTR(-ENOMEM); | ||
483 | } | ||
484 | |||
485 | state->name = name; | ||
486 | INIT_LIST_HEAD(&state->settings); | ||
487 | |||
488 | list_add_tail(&state->node, &p->states); | ||
489 | |||
490 | return state; | ||
491 | } | ||
492 | |||
493 | static int add_setting(struct pinctrl *p, struct pinctrl_map const *map) | ||
494 | { | ||
495 | struct pinctrl_state *state; | ||
471 | struct pinctrl_setting *setting; | 496 | struct pinctrl_setting *setting; |
497 | int ret; | ||
472 | 498 | ||
473 | /* We must have both a dev and state name */ | 499 | state = find_state(p, map->name); |
474 | if (WARN_ON(!dev || !name)) | 500 | if (!state) |
475 | return ERR_PTR(-EINVAL); | 501 | state = create_state(p, map->name); |
502 | if (IS_ERR(state)) | ||
503 | return PTR_ERR(state); | ||
476 | 504 | ||
477 | devname = dev_name(dev); | 505 | setting = kzalloc(sizeof(*setting), GFP_KERNEL); |
506 | if (setting == NULL) { | ||
507 | dev_err(p->dev, | ||
508 | "failed to alloc struct pinctrl_setting\n"); | ||
509 | return -ENOMEM; | ||
510 | } | ||
478 | 511 | ||
479 | dev_dbg(dev, "pinctrl_get() for device %s state %s\n", devname, name); | 512 | setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name); |
513 | if (setting->pctldev == NULL) { | ||
514 | dev_err(p->dev, "unknown pinctrl device %s in map entry", | ||
515 | map->ctrl_dev_name); | ||
516 | kfree(setting); | ||
517 | /* Eventually, this should trigger deferred probe */ | ||
518 | return -ENODEV; | ||
519 | } | ||
520 | |||
521 | ret = pinmux_map_to_setting(map, setting); | ||
522 | if (ret < 0) { | ||
523 | kfree(setting); | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | list_add_tail(&setting->node, &state->settings); | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | static struct pinctrl *find_pinctrl(struct device *dev) | ||
533 | { | ||
534 | struct pinctrl *p; | ||
535 | |||
536 | list_for_each_entry(p, &pinctrldev_list, node) | ||
537 | if (p->dev == dev) | ||
538 | return p; | ||
539 | |||
540 | return NULL; | ||
541 | } | ||
542 | |||
543 | static void pinctrl_put_locked(struct pinctrl *p, bool inlist); | ||
544 | |||
545 | static struct pinctrl *create_pinctrl(struct device *dev) | ||
546 | { | ||
547 | struct pinctrl *p; | ||
548 | const char *devname; | ||
549 | struct pinctrl_maps *maps_node; | ||
550 | int i; | ||
551 | struct pinctrl_map const *map; | ||
552 | int ret; | ||
480 | 553 | ||
481 | /* | 554 | /* |
482 | * create the state cookie holder struct pinctrl for each | 555 | * create the state cookie holder struct pinctrl for each |
@@ -489,8 +562,9 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name) | |||
489 | return ERR_PTR(-ENOMEM); | 562 | return ERR_PTR(-ENOMEM); |
490 | } | 563 | } |
491 | p->dev = dev; | 564 | p->dev = dev; |
492 | p->state = name; | 565 | INIT_LIST_HEAD(&p->states); |
493 | INIT_LIST_HEAD(&p->settings); | 566 | |
567 | devname = dev_name(dev); | ||
494 | 568 | ||
495 | /* Iterate over the pin control maps to locate the right ones */ | 569 | /* Iterate over the pin control maps to locate the right ones */ |
496 | for_each_maps(maps_node, i, map) { | 570 | for_each_maps(maps_node, i, map) { |
@@ -498,183 +572,179 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name) | |||
498 | if (strcmp(map->dev_name, devname)) | 572 | if (strcmp(map->dev_name, devname)) |
499 | continue; | 573 | continue; |
500 | 574 | ||
501 | /* State name must be the one we're looking for */ | 575 | ret = add_setting(p, map); |
502 | if (strcmp(map->name, name)) | 576 | if (ret < 0) { |
503 | continue; | 577 | pinctrl_put_locked(p, false); |
504 | 578 | return ERR_PTR(ret); | |
505 | /* | ||
506 | * Try to find the pctldev given in the map | ||
507 | */ | ||
508 | pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name); | ||
509 | if (!pctldev) { | ||
510 | dev_err(dev, "unknown pinctrl device %s in map entry", | ||
511 | map->ctrl_dev_name); | ||
512 | /* Eventually, this should trigger deferred probe */ | ||
513 | ret = -ENODEV; | ||
514 | goto error; | ||
515 | } | ||
516 | |||
517 | dev_dbg(dev, "in map, found pctldev %s to handle function %s", | ||
518 | dev_name(pctldev->dev), map->function); | ||
519 | |||
520 | setting = kzalloc(sizeof(*setting), GFP_KERNEL); | ||
521 | if (setting == NULL) { | ||
522 | dev_err(dev, | ||
523 | "failed to alloc struct pinctrl_setting\n"); | ||
524 | ret = -ENOMEM; | ||
525 | goto error; | ||
526 | } | 579 | } |
527 | |||
528 | setting->pctldev = pctldev; | ||
529 | ret = pinmux_map_to_setting(map, setting); | ||
530 | if (ret < 0) | ||
531 | goto error; | ||
532 | |||
533 | list_add_tail(&setting->node, &p->settings); | ||
534 | |||
535 | num_maps++; | ||
536 | } | 580 | } |
537 | 581 | ||
538 | /* | ||
539 | * This may be perfectly legitimate. An IP block may get re-used | ||
540 | * across SoCs. Not all of those SoCs may need pinmux settings for the | ||
541 | * IP block, e.g. if one SoC dedicates pins to that function but | ||
542 | * another doesn't. The driver won't know this, and will always | ||
543 | * attempt to set up the pinmux. The mapping table defines whether any | ||
544 | * HW programming is actually needed. | ||
545 | */ | ||
546 | if (!num_maps) | ||
547 | dev_info(dev, "zero maps found for mapping %s\n", name); | ||
548 | |||
549 | dev_dbg(dev, "found %u maps for device %s state %s\n", | ||
550 | num_maps, devname, name ? name : "(undefined)"); | ||
551 | |||
552 | /* Add the pinmux to the global list */ | 582 | /* Add the pinmux to the global list */ |
553 | list_add_tail(&p->node, &pinctrl_list); | 583 | list_add_tail(&p->node, &pinctrl_list); |
554 | 584 | ||
555 | return p; | 585 | return p; |
586 | } | ||
556 | 587 | ||
557 | error: | 588 | static struct pinctrl *pinctrl_get_locked(struct device *dev) |
558 | list_for_each_entry(setting, &p->settings, node) | 589 | { |
559 | pinmux_free_setting(setting); | 590 | struct pinctrl *p; |
560 | 591 | ||
561 | kfree(p); | 592 | if (WARN_ON(!dev)) |
593 | return ERR_PTR(-EINVAL); | ||
594 | |||
595 | p = find_pinctrl(dev); | ||
596 | if (p != NULL) | ||
597 | return ERR_PTR(-EBUSY); | ||
562 | 598 | ||
563 | return ERR_PTR(ret); | 599 | p = create_pinctrl(dev); |
600 | if (IS_ERR(p)) | ||
601 | return p; | ||
602 | |||
603 | return p; | ||
564 | } | 604 | } |
565 | 605 | ||
566 | /** | 606 | /** |
567 | * pinctrl_get() - retrieves the pin controller handle for a certain device | 607 | * pinctrl_get() - retrieves the pinctrl handle for a device |
568 | * @dev: the device to get the pin controller handle for | 608 | * @dev: the device to obtain the handle for |
569 | * @name: an optional specific control mapping name or NULL, the name is only | ||
570 | * needed if you want to have more than one mapping per device, or if you | ||
571 | * need an anonymous pin control (not tied to any specific device) | ||
572 | */ | 609 | */ |
573 | struct pinctrl *pinctrl_get(struct device *dev, const char *name) | 610 | struct pinctrl *pinctrl_get(struct device *dev) |
574 | { | 611 | { |
575 | struct pinctrl *p; | 612 | struct pinctrl *p; |
576 | 613 | ||
577 | mutex_lock(&pinctrl_mutex); | 614 | mutex_lock(&pinctrl_mutex); |
578 | p = pinctrl_get_locked(dev, name); | 615 | p = pinctrl_get_locked(dev); |
579 | mutex_unlock(&pinctrl_mutex); | 616 | mutex_unlock(&pinctrl_mutex); |
580 | 617 | ||
581 | return p; | 618 | return p; |
582 | } | 619 | } |
583 | EXPORT_SYMBOL_GPL(pinctrl_get); | 620 | EXPORT_SYMBOL_GPL(pinctrl_get); |
584 | 621 | ||
585 | static void pinctrl_put_locked(struct pinctrl *p) | 622 | static void pinctrl_put_locked(struct pinctrl *p, bool inlist) |
586 | { | 623 | { |
587 | struct pinctrl_setting *setting, *n; | 624 | struct pinctrl_state *state, *n1; |
588 | 625 | struct pinctrl_setting *setting, *n2; | |
589 | if (p == NULL) | 626 | |
590 | return; | 627 | list_for_each_entry_safe(state, n1, &p->states, node) { |
591 | 628 | list_for_each_entry_safe(setting, n2, &state->settings, node) { | |
592 | if (p->usecount) | 629 | if (state == p->state) |
593 | pr_warn("releasing pin control handle with active users!\n"); | 630 | pinmux_disable_setting(setting); |
594 | list_for_each_entry_safe(setting, n, &p->settings, node) { | 631 | pinmux_free_setting(setting); |
595 | pinmux_free_setting(setting); | 632 | list_del(&setting->node); |
596 | list_del(&setting->node); | 633 | kfree(setting); |
597 | kfree(setting); | 634 | } |
635 | list_del(&state->node); | ||
636 | kfree(state); | ||
598 | } | 637 | } |
599 | 638 | ||
600 | /* Remove from list */ | 639 | if (inlist) |
601 | list_del(&p->node); | 640 | list_del(&p->node); |
602 | |||
603 | kfree(p); | 641 | kfree(p); |
604 | } | 642 | } |
605 | 643 | ||
606 | /** | 644 | /** |
607 | * pinctrl_put() - release a previously claimed pin control handle | 645 | * pinctrl_put() - release a previously claimed pinctrl handle |
608 | * @p: a pin control handle previously claimed by pinctrl_get() | 646 | * @p: the pinctrl handle to release |
609 | */ | 647 | */ |
610 | void pinctrl_put(struct pinctrl *p) | 648 | void pinctrl_put(struct pinctrl *p) |
611 | { | 649 | { |
612 | mutex_lock(&pinctrl_mutex); | 650 | mutex_lock(&pinctrl_mutex); |
613 | pinctrl_put(p); | 651 | pinctrl_put_locked(p, true); |
614 | mutex_unlock(&pinctrl_mutex); | 652 | mutex_unlock(&pinctrl_mutex); |
615 | } | 653 | } |
616 | EXPORT_SYMBOL_GPL(pinctrl_put); | 654 | EXPORT_SYMBOL_GPL(pinctrl_put); |
617 | 655 | ||
618 | static int pinctrl_enable_locked(struct pinctrl *p) | 656 | static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p, |
657 | const char *name) | ||
619 | { | 658 | { |
620 | struct pinctrl_setting *setting; | 659 | struct pinctrl_state *state; |
621 | int ret; | ||
622 | 660 | ||
623 | if (p == NULL) | 661 | state = find_state(p, name); |
624 | return -EINVAL; | 662 | if (!state) |
663 | return ERR_PTR(-ENODEV); | ||
625 | 664 | ||
626 | if (p->usecount++ == 0) { | 665 | return state; |
627 | list_for_each_entry(setting, &p->settings, node) { | ||
628 | ret = pinmux_enable_setting(setting); | ||
629 | if (ret < 0) { | ||
630 | /* FIXME: Difficult to return to prev state */ | ||
631 | p->usecount--; | ||
632 | return ret; | ||
633 | } | ||
634 | } | ||
635 | } | ||
636 | |||
637 | return 0; | ||
638 | } | 666 | } |
639 | 667 | ||
640 | /** | 668 | /** |
641 | * pinctrl_enable() - enable a certain pin controller setting | 669 | * pinctrl_lookup_state() - retrieves a state handle from a pinctrl handle |
642 | * @p: the pin control handle to enable, previously claimed by pinctrl_get() | 670 | * @p: the pinctrl handle to retrieve the state from |
671 | * @name: the state name to retrieve | ||
643 | */ | 672 | */ |
644 | int pinctrl_enable(struct pinctrl *p) | 673 | struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name) |
645 | { | 674 | { |
646 | int ret; | 675 | struct pinctrl_state *s; |
676 | |||
647 | mutex_lock(&pinctrl_mutex); | 677 | mutex_lock(&pinctrl_mutex); |
648 | ret = pinctrl_enable_locked(p); | 678 | s = pinctrl_lookup_state_locked(p, name); |
649 | mutex_unlock(&pinctrl_mutex); | 679 | mutex_unlock(&pinctrl_mutex); |
650 | return ret; | 680 | |
681 | return s; | ||
651 | } | 682 | } |
652 | EXPORT_SYMBOL_GPL(pinctrl_enable); | 683 | EXPORT_SYMBOL_GPL(pinctrl_lookup_state); |
653 | 684 | ||
654 | static void pinctrl_disable_locked(struct pinctrl *p) | 685 | static int pinctrl_select_state_locked(struct pinctrl *p, |
686 | struct pinctrl_state *state) | ||
655 | { | 687 | { |
656 | struct pinctrl_setting *setting; | 688 | struct pinctrl_setting *setting, *setting2; |
689 | int ret; | ||
657 | 690 | ||
658 | if (p == NULL) | 691 | if (p->state == state) |
659 | return; | 692 | return 0; |
660 | 693 | ||
661 | if (--p->usecount == 0) { | 694 | if (p->state) { |
662 | list_for_each_entry(setting, &p->settings, node) | 695 | /* |
663 | pinmux_disable_setting(setting); | 696 | * The set of groups with a mux configuration in the old state |
697 | * may not be identical to the set of groups with a mux setting | ||
698 | * in the new state. While this might be unusual, it's entirely | ||
699 | * possible for the "user"-supplied mapping table to be written | ||
700 | * that way. For each group that was configured in the old state | ||
701 | * but not in the new state, this code puts that group into a | ||
702 | * safe/disabled state. | ||
703 | */ | ||
704 | list_for_each_entry(setting, &p->state->settings, node) { | ||
705 | bool found = false; | ||
706 | list_for_each_entry(setting2, &state->settings, node) { | ||
707 | if (setting2->group_selector == | ||
708 | setting->group_selector) { | ||
709 | found = true; | ||
710 | break; | ||
711 | } | ||
712 | } | ||
713 | if (!found) | ||
714 | pinmux_disable_setting(setting); | ||
715 | } | ||
716 | } | ||
717 | |||
718 | p->state = state; | ||
719 | |||
720 | /* Apply all the settings for the new state */ | ||
721 | list_for_each_entry(setting, &state->settings, node) { | ||
722 | ret = pinmux_enable_setting(setting); | ||
723 | if (ret < 0) { | ||
724 | /* FIXME: Difficult to return to prev state */ | ||
725 | return ret; | ||
726 | } | ||
664 | } | 727 | } |
728 | |||
729 | return 0; | ||
665 | } | 730 | } |
666 | 731 | ||
667 | /** | 732 | /** |
668 | * pinctrl_disable() - disable a certain pin control setting | 733 | * pinctrl_select() - select/activate/program a pinctrl state to HW |
669 | * @p: the pin control handle to disable, previously claimed by pinctrl_get() | 734 | * @p: the pinctrl handle for the device that requests configuratio |
735 | * @state: the state handle to select/activate/program | ||
670 | */ | 736 | */ |
671 | void pinctrl_disable(struct pinctrl *p) | 737 | int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state) |
672 | { | 738 | { |
739 | int ret; | ||
740 | |||
673 | mutex_lock(&pinctrl_mutex); | 741 | mutex_lock(&pinctrl_mutex); |
674 | pinctrl_disable_locked(p); | 742 | ret = pinctrl_select_state_locked(p, state); |
675 | mutex_unlock(&pinctrl_mutex); | 743 | mutex_unlock(&pinctrl_mutex); |
744 | |||
745 | return ret; | ||
676 | } | 746 | } |
677 | EXPORT_SYMBOL_GPL(pinctrl_disable); | 747 | EXPORT_SYMBOL_GPL(pinctrl_select_state); |
678 | 748 | ||
679 | /** | 749 | /** |
680 | * pinctrl_register_mappings() - register a set of pin controller mappings | 750 | * pinctrl_register_mappings() - register a set of pin controller mappings |
@@ -891,6 +961,7 @@ static int pinctrl_maps_show(struct seq_file *s, void *what) | |||
891 | static int pinctrl_show(struct seq_file *s, void *what) | 961 | static int pinctrl_show(struct seq_file *s, void *what) |
892 | { | 962 | { |
893 | struct pinctrl *p; | 963 | struct pinctrl *p; |
964 | struct pinctrl_state *state; | ||
894 | struct pinctrl_setting *setting; | 965 | struct pinctrl_setting *setting; |
895 | 966 | ||
896 | seq_puts(s, "Requested pin control handlers their pinmux maps:\n"); | 967 | seq_puts(s, "Requested pin control handlers their pinmux maps:\n"); |
@@ -898,12 +969,17 @@ static int pinctrl_show(struct seq_file *s, void *what) | |||
898 | mutex_lock(&pinctrl_mutex); | 969 | mutex_lock(&pinctrl_mutex); |
899 | 970 | ||
900 | list_for_each_entry(p, &pinctrl_list, node) { | 971 | list_for_each_entry(p, &pinctrl_list, node) { |
901 | seq_printf(s, "device: %s state: %s users: %u\n", | 972 | seq_printf(s, "device: %s current state: %s\n", |
902 | dev_name(p->dev), p->state, p->usecount); | 973 | dev_name(p->dev), |
974 | p->state ? p->state->name : "none"); | ||
975 | |||
976 | list_for_each_entry(state, &p->states, node) { | ||
977 | seq_printf(s, " state: %s\n", state->name); | ||
903 | 978 | ||
904 | list_for_each_entry(setting, &p->settings, node) { | 979 | list_for_each_entry(setting, &state->settings, node) { |
905 | seq_printf(s, " "); | 980 | seq_printf(s, " "); |
906 | pinmux_dbg_show(s, setting); | 981 | pinmux_dbg_show(s, setting); |
982 | } | ||
907 | } | 983 | } |
908 | } | 984 | } |
909 | 985 | ||
@@ -1113,9 +1189,14 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, | |||
1113 | 1189 | ||
1114 | list_add_tail(&pctldev->node, &pinctrldev_list); | 1190 | list_add_tail(&pctldev->node, &pinctrldev_list); |
1115 | 1191 | ||
1116 | pctldev->p = pinctrl_get_locked(pctldev->dev, PINCTRL_STATE_DEFAULT); | 1192 | pctldev->p = pinctrl_get_locked(pctldev->dev); |
1117 | if (!IS_ERR(pctldev->p)) | 1193 | if (!IS_ERR(pctldev->p)) { |
1118 | pinctrl_enable_locked(pctldev->p); | 1194 | struct pinctrl_state *s = |
1195 | pinctrl_lookup_state_locked(pctldev->p, | ||
1196 | PINCTRL_STATE_DEFAULT); | ||
1197 | if (!IS_ERR(s)) | ||
1198 | pinctrl_select_state_locked(pctldev->p, s); | ||
1199 | } | ||
1119 | 1200 | ||
1120 | mutex_unlock(&pinctrl_mutex); | 1201 | mutex_unlock(&pinctrl_mutex); |
1121 | 1202 | ||
@@ -1144,10 +1225,8 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) | |||
1144 | 1225 | ||
1145 | mutex_lock(&pinctrl_mutex); | 1226 | mutex_lock(&pinctrl_mutex); |
1146 | 1227 | ||
1147 | if (!IS_ERR(pctldev->p)) { | 1228 | if (!IS_ERR(pctldev->p)) |
1148 | pinctrl_disable_locked(pctldev->p); | 1229 | pinctrl_put_locked(pctldev->p, true); |
1149 | pinctrl_put_locked(pctldev->p); | ||
1150 | } | ||
1151 | 1230 | ||
1152 | /* TODO: check that no pinmuxes are still active? */ | 1231 | /* TODO: check that no pinmuxes are still active? */ |
1153 | list_del(&pctldev->node); | 1232 | list_del(&pctldev->node); |
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 0bc52ecaf710..5691d312e15a 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h | |||
@@ -49,22 +49,31 @@ struct pinctrl_dev { | |||
49 | * struct pinctrl - per-device pin control state holder | 49 | * struct pinctrl - per-device pin control state holder |
50 | * @node: global list node | 50 | * @node: global list node |
51 | * @dev: the device using this pin control handle | 51 | * @dev: the device using this pin control handle |
52 | * @state: the state name passed to pinctrl_get() | 52 | * @states: a list of states for this device |
53 | * @usecount: the number of active users of this pin controller setting, used | 53 | * @state: the current state |
54 | * to keep track of nested use cases | ||
55 | * @settings: a list of settings for this device/state | ||
56 | */ | 54 | */ |
57 | struct pinctrl { | 55 | struct pinctrl { |
58 | struct list_head node; | 56 | struct list_head node; |
59 | struct device *dev; | 57 | struct device *dev; |
60 | const char *state; | 58 | struct list_head states; |
61 | unsigned usecount; | 59 | struct pinctrl_state *state; |
60 | }; | ||
61 | |||
62 | /** | ||
63 | * struct pinctrl_state - a pinctrl state for a device | ||
64 | * @node: list not for struct pinctrl's @states field | ||
65 | * @name: the name of this state | ||
66 | * @settings: a list of settings for this state | ||
67 | */ | ||
68 | struct pinctrl_state { | ||
69 | struct list_head node; | ||
70 | const char *name; | ||
62 | struct list_head settings; | 71 | struct list_head settings; |
63 | }; | 72 | }; |
64 | 73 | ||
65 | /** | 74 | /** |
66 | * struct pinctrl_setting - an individual mux setting | 75 | * struct pinctrl_setting - an individual mux setting |
67 | * @node: list node for struct pinctrl's @settings field | 76 | * @node: list node for struct pinctrl_settings's @settings field |
68 | * @pctldev: pin control device handling to be programmed | 77 | * @pctldev: pin control device handling to be programmed |
69 | * @group_selector: the group selector to program | 78 | * @group_selector: the group selector to program |
70 | * @func_selector: the function selector to program | 79 | * @func_selector: the function selector to program |