diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2008-10-16 01:03:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-16 14:21:40 -0400 |
commit | 35e8bb5175c1a6ff6253f1a2acb30bfe52a2f500 (patch) | |
tree | 88a1e9695824f88efef3340fd53f8dbe576f5852 /drivers | |
parent | 93a22f8b95756c53e80308820892119c910d2739 (diff) |
gpiolib: request/free hooks
Add a new internal mechanism to gpiolib to support low power
operations by letting gpio_chip instances see when their GPIOs
are in use. When no GPIOs are active, chips may be able to
enter lower powered runtime states by disabling clocks and/or
power domains.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: "Magnus Damm" <magnus.damm@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/gpiolib.c | 91 |
1 files changed, 78 insertions, 13 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 29a7e6b1be5d..9112830107a5 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -67,17 +67,28 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label) | |||
67 | * when setting direction, and otherwise illegal. Until board setup code | 67 | * when setting direction, and otherwise illegal. Until board setup code |
68 | * and drivers use explicit requests everywhere (which won't happen when | 68 | * and drivers use explicit requests everywhere (which won't happen when |
69 | * those calls have no teeth) we can't avoid autorequesting. This nag | 69 | * those calls have no teeth) we can't avoid autorequesting. This nag |
70 | * message should motivate switching to explicit requests... | 70 | * message should motivate switching to explicit requests... so should |
71 | * the weaker cleanup after faults, compared to gpio_request(). | ||
71 | */ | 72 | */ |
72 | static void gpio_ensure_requested(struct gpio_desc *desc) | 73 | static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset) |
73 | { | 74 | { |
74 | if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { | 75 | if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { |
75 | pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc)); | 76 | struct gpio_chip *chip = desc->chip; |
77 | int gpio = chip->base + offset; | ||
78 | |||
79 | if (!try_module_get(chip->owner)) { | ||
80 | pr_err("GPIO-%d: module can't be gotten \n", gpio); | ||
81 | clear_bit(FLAG_REQUESTED, &desc->flags); | ||
82 | /* lose */ | ||
83 | return -EIO; | ||
84 | } | ||
85 | pr_warning("GPIO-%d autorequested\n", gpio); | ||
76 | desc_set_label(desc, "[auto]"); | 86 | desc_set_label(desc, "[auto]"); |
77 | if (!try_module_get(desc->chip->owner)) | 87 | /* caller must chip->request() w/o spinlock */ |
78 | pr_err("GPIO-%d: module can't be gotten \n", | 88 | if (chip->request) |
79 | (int)(desc - gpio_desc)); | 89 | return 1; |
80 | } | 90 | } |
91 | return 0; | ||
81 | } | 92 | } |
82 | 93 | ||
83 | /* caller holds gpio_lock *OR* gpio is marked as requested */ | 94 | /* caller holds gpio_lock *OR* gpio is marked as requested */ |
@@ -752,6 +763,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove); | |||
752 | int gpio_request(unsigned gpio, const char *label) | 763 | int gpio_request(unsigned gpio, const char *label) |
753 | { | 764 | { |
754 | struct gpio_desc *desc; | 765 | struct gpio_desc *desc; |
766 | struct gpio_chip *chip; | ||
755 | int status = -EINVAL; | 767 | int status = -EINVAL; |
756 | unsigned long flags; | 768 | unsigned long flags; |
757 | 769 | ||
@@ -760,14 +772,15 @@ int gpio_request(unsigned gpio, const char *label) | |||
760 | if (!gpio_is_valid(gpio)) | 772 | if (!gpio_is_valid(gpio)) |
761 | goto done; | 773 | goto done; |
762 | desc = &gpio_desc[gpio]; | 774 | desc = &gpio_desc[gpio]; |
763 | if (desc->chip == NULL) | 775 | chip = desc->chip; |
776 | if (chip == NULL) | ||
764 | goto done; | 777 | goto done; |
765 | 778 | ||
766 | if (!try_module_get(desc->chip->owner)) | 779 | if (!try_module_get(chip->owner)) |
767 | goto done; | 780 | goto done; |
768 | 781 | ||
769 | /* NOTE: gpio_request() can be called in early boot, | 782 | /* NOTE: gpio_request() can be called in early boot, |
770 | * before IRQs are enabled. | 783 | * before IRQs are enabled, for non-sleeping (SOC) GPIOs. |
771 | */ | 784 | */ |
772 | 785 | ||
773 | if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { | 786 | if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { |
@@ -775,7 +788,20 @@ int gpio_request(unsigned gpio, const char *label) | |||
775 | status = 0; | 788 | status = 0; |
776 | } else { | 789 | } else { |
777 | status = -EBUSY; | 790 | status = -EBUSY; |
778 | module_put(desc->chip->owner); | 791 | module_put(chip->owner); |
792 | } | ||
793 | |||
794 | if (chip->request) { | ||
795 | /* chip->request may sleep */ | ||
796 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
797 | status = chip->request(chip, gpio - chip->base); | ||
798 | spin_lock_irqsave(&gpio_lock, flags); | ||
799 | |||
800 | if (status < 0) { | ||
801 | desc_set_label(desc, NULL); | ||
802 | module_put(chip->owner); | ||
803 | clear_bit(FLAG_REQUESTED, &desc->flags); | ||
804 | } | ||
779 | } | 805 | } |
780 | 806 | ||
781 | done: | 807 | done: |
@@ -791,6 +817,7 @@ void gpio_free(unsigned gpio) | |||
791 | { | 817 | { |
792 | unsigned long flags; | 818 | unsigned long flags; |
793 | struct gpio_desc *desc; | 819 | struct gpio_desc *desc; |
820 | struct gpio_chip *chip; | ||
794 | 821 | ||
795 | might_sleep(); | 822 | might_sleep(); |
796 | 823 | ||
@@ -804,9 +831,17 @@ void gpio_free(unsigned gpio) | |||
804 | spin_lock_irqsave(&gpio_lock, flags); | 831 | spin_lock_irqsave(&gpio_lock, flags); |
805 | 832 | ||
806 | desc = &gpio_desc[gpio]; | 833 | desc = &gpio_desc[gpio]; |
807 | if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) { | 834 | chip = desc->chip; |
835 | if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { | ||
836 | if (chip->free) { | ||
837 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
838 | might_sleep_if(extra_checks && chip->can_sleep); | ||
839 | chip->free(chip, gpio - chip->base); | ||
840 | spin_lock_irqsave(&gpio_lock, flags); | ||
841 | } | ||
808 | desc_set_label(desc, NULL); | 842 | desc_set_label(desc, NULL); |
809 | module_put(desc->chip->owner); | 843 | module_put(desc->chip->owner); |
844 | clear_bit(FLAG_REQUESTED, &desc->flags); | ||
810 | } else | 845 | } else |
811 | WARN_ON(extra_checks); | 846 | WARN_ON(extra_checks); |
812 | 847 | ||
@@ -871,7 +906,9 @@ int gpio_direction_input(unsigned gpio) | |||
871 | gpio -= chip->base; | 906 | gpio -= chip->base; |
872 | if (gpio >= chip->ngpio) | 907 | if (gpio >= chip->ngpio) |
873 | goto fail; | 908 | goto fail; |
874 | gpio_ensure_requested(desc); | 909 | status = gpio_ensure_requested(desc, gpio); |
910 | if (status < 0) | ||
911 | goto fail; | ||
875 | 912 | ||
876 | /* now we know the gpio is valid and chip won't vanish */ | 913 | /* now we know the gpio is valid and chip won't vanish */ |
877 | 914 | ||
@@ -879,9 +916,22 @@ int gpio_direction_input(unsigned gpio) | |||
879 | 916 | ||
880 | might_sleep_if(extra_checks && chip->can_sleep); | 917 | might_sleep_if(extra_checks && chip->can_sleep); |
881 | 918 | ||
919 | if (status) { | ||
920 | status = chip->request(chip, gpio); | ||
921 | if (status < 0) { | ||
922 | pr_debug("GPIO-%d: chip request fail, %d\n", | ||
923 | chip->base + gpio, status); | ||
924 | /* and it's not available to anyone else ... | ||
925 | * gpio_request() is the fully clean solution. | ||
926 | */ | ||
927 | goto lose; | ||
928 | } | ||
929 | } | ||
930 | |||
882 | status = chip->direction_input(chip, gpio); | 931 | status = chip->direction_input(chip, gpio); |
883 | if (status == 0) | 932 | if (status == 0) |
884 | clear_bit(FLAG_IS_OUT, &desc->flags); | 933 | clear_bit(FLAG_IS_OUT, &desc->flags); |
934 | lose: | ||
885 | return status; | 935 | return status; |
886 | fail: | 936 | fail: |
887 | spin_unlock_irqrestore(&gpio_lock, flags); | 937 | spin_unlock_irqrestore(&gpio_lock, flags); |
@@ -909,7 +959,9 @@ int gpio_direction_output(unsigned gpio, int value) | |||
909 | gpio -= chip->base; | 959 | gpio -= chip->base; |
910 | if (gpio >= chip->ngpio) | 960 | if (gpio >= chip->ngpio) |
911 | goto fail; | 961 | goto fail; |
912 | gpio_ensure_requested(desc); | 962 | status = gpio_ensure_requested(desc, gpio); |
963 | if (status < 0) | ||
964 | goto fail; | ||
913 | 965 | ||
914 | /* now we know the gpio is valid and chip won't vanish */ | 966 | /* now we know the gpio is valid and chip won't vanish */ |
915 | 967 | ||
@@ -917,9 +969,22 @@ int gpio_direction_output(unsigned gpio, int value) | |||
917 | 969 | ||
918 | might_sleep_if(extra_checks && chip->can_sleep); | 970 | might_sleep_if(extra_checks && chip->can_sleep); |
919 | 971 | ||
972 | if (status) { | ||
973 | status = chip->request(chip, gpio); | ||
974 | if (status < 0) { | ||
975 | pr_debug("GPIO-%d: chip request fail, %d\n", | ||
976 | chip->base + gpio, status); | ||
977 | /* and it's not available to anyone else ... | ||
978 | * gpio_request() is the fully clean solution. | ||
979 | */ | ||
980 | goto lose; | ||
981 | } | ||
982 | } | ||
983 | |||
920 | status = chip->direction_output(chip, gpio, value); | 984 | status = chip->direction_output(chip, gpio, value); |
921 | if (status == 0) | 985 | if (status == 0) |
922 | set_bit(FLAG_IS_OUT, &desc->flags); | 986 | set_bit(FLAG_IS_OUT, &desc->flags); |
987 | lose: | ||
923 | return status; | 988 | return status; |
924 | fail: | 989 | fail: |
925 | spin_unlock_irqrestore(&gpio_lock, flags); | 990 | spin_unlock_irqrestore(&gpio_lock, flags); |