Commit 35e8bb5175c1a6ff6253f1a2acb30bfe52a2f500
Committed by
Linus Torvalds
1 parent
93a22f8b95
Exists in
master
and in
20 other branches
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>
Showing 3 changed files with 91 additions and 13 deletions Side-by-side Diff
Documentation/gpio.txt
... | ... | @@ -240,6 +240,10 @@ |
240 | 240 | needed to manage a signal that's in active use. That is, requesting a |
241 | 241 | GPIO can serve as a kind of lock. |
242 | 242 | |
243 | +Some platforms may also use knowledge about what GPIOs are active for | |
244 | +power management, such as by powering down unused chip sectors and, more | |
245 | +easily, gating off unused clocks. | |
246 | + | |
243 | 247 | These two calls are optional because not not all current Linux platforms |
244 | 248 | offer such functionality in their GPIO support; a valid implementation |
245 | 249 | could return success for all gpio_request() calls. Unlike the other calls, |
drivers/gpio/gpiolib.c
... | ... | @@ -67,17 +67,28 @@ |
67 | 67 | * when setting direction, and otherwise illegal. Until board setup code |
68 | 68 | * and drivers use explicit requests everywhere (which won't happen when |
69 | 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 | 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 | 86 | desc_set_label(desc, "[auto]"); |
77 | - if (!try_module_get(desc->chip->owner)) | |
78 | - pr_err("GPIO-%d: module can't be gotten \n", | |
79 | - (int)(desc - gpio_desc)); | |
87 | + /* caller must chip->request() w/o spinlock */ | |
88 | + if (chip->request) | |
89 | + return 1; | |
80 | 90 | } |
91 | + return 0; | |
81 | 92 | } |
82 | 93 | |
83 | 94 | /* caller holds gpio_lock *OR* gpio is marked as requested */ |
... | ... | @@ -752,6 +763,7 @@ |
752 | 763 | int gpio_request(unsigned gpio, const char *label) |
753 | 764 | { |
754 | 765 | struct gpio_desc *desc; |
766 | + struct gpio_chip *chip; | |
755 | 767 | int status = -EINVAL; |
756 | 768 | unsigned long flags; |
757 | 769 | |
758 | 770 | |
759 | 771 | |
... | ... | @@ -760,14 +772,15 @@ |
760 | 772 | if (!gpio_is_valid(gpio)) |
761 | 773 | goto done; |
762 | 774 | desc = &gpio_desc[gpio]; |
763 | - if (desc->chip == NULL) | |
775 | + chip = desc->chip; | |
776 | + if (chip == NULL) | |
764 | 777 | goto done; |
765 | 778 | |
766 | - if (!try_module_get(desc->chip->owner)) | |
779 | + if (!try_module_get(chip->owner)) | |
767 | 780 | goto done; |
768 | 781 | |
769 | 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 | 786 | if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { |
774 | 787 | |
... | ... | @@ -775,9 +788,22 @@ |
775 | 788 | status = 0; |
776 | 789 | } else { |
777 | 790 | status = -EBUSY; |
778 | - module_put(desc->chip->owner); | |
791 | + module_put(chip->owner); | |
779 | 792 | } |
780 | 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 | + } | |
805 | + } | |
806 | + | |
781 | 807 | done: |
782 | 808 | if (status) |
783 | 809 | pr_debug("gpio_request: gpio-%d (%s) status %d\n", |
... | ... | @@ -791,6 +817,7 @@ |
791 | 817 | { |
792 | 818 | unsigned long flags; |
793 | 819 | struct gpio_desc *desc; |
820 | + struct gpio_chip *chip; | |
794 | 821 | |
795 | 822 | might_sleep(); |
796 | 823 | |
797 | 824 | |
... | ... | @@ -804,9 +831,17 @@ |
804 | 831 | spin_lock_irqsave(&gpio_lock, flags); |
805 | 832 | |
806 | 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 | 842 | desc_set_label(desc, NULL); |
809 | 843 | module_put(desc->chip->owner); |
844 | + clear_bit(FLAG_REQUESTED, &desc->flags); | |
810 | 845 | } else |
811 | 846 | WARN_ON(extra_checks); |
812 | 847 | |
... | ... | @@ -871,7 +906,9 @@ |
871 | 906 | gpio -= chip->base; |
872 | 907 | if (gpio >= chip->ngpio) |
873 | 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 | 913 | /* now we know the gpio is valid and chip won't vanish */ |
877 | 914 | |
878 | 915 | |
... | ... | @@ -879,9 +916,22 @@ |
879 | 916 | |
880 | 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 | 931 | status = chip->direction_input(chip, gpio); |
883 | 932 | if (status == 0) |
884 | 933 | clear_bit(FLAG_IS_OUT, &desc->flags); |
934 | +lose: | |
885 | 935 | return status; |
886 | 936 | fail: |
887 | 937 | spin_unlock_irqrestore(&gpio_lock, flags); |
... | ... | @@ -909,7 +959,9 @@ |
909 | 959 | gpio -= chip->base; |
910 | 960 | if (gpio >= chip->ngpio) |
911 | 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 | 966 | /* now we know the gpio is valid and chip won't vanish */ |
915 | 967 | |
916 | 968 | |
... | ... | @@ -917,9 +969,22 @@ |
917 | 969 | |
918 | 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 | 984 | status = chip->direction_output(chip, gpio, value); |
921 | 985 | if (status == 0) |
922 | 986 | set_bit(FLAG_IS_OUT, &desc->flags); |
987 | +lose: | |
923 | 988 | return status; |
924 | 989 | fail: |
925 | 990 | spin_unlock_irqrestore(&gpio_lock, flags); |
include/asm-generic/gpio.h
... | ... | @@ -35,6 +35,10 @@ |
35 | 35 | * @label: for diagnostics |
36 | 36 | * @dev: optional device providing the GPIOs |
37 | 37 | * @owner: helps prevent removal of modules exporting active GPIOs |
38 | + * @request: optional hook for chip-specific activation, such as | |
39 | + * enabling module power and clock; may sleep | |
40 | + * @free: optional hook for chip-specific deactivation, such as | |
41 | + * disabling module power and clock; may sleep | |
38 | 42 | * @direction_input: configures signal "offset" as input, or returns error |
39 | 43 | * @get: returns value for signal "offset"; for output signals this |
40 | 44 | * returns either the value actually sensed, or zero |
... | ... | @@ -66,6 +70,11 @@ |
66 | 70 | const char *label; |
67 | 71 | struct device *dev; |
68 | 72 | struct module *owner; |
73 | + | |
74 | + int (*request)(struct gpio_chip *chip, | |
75 | + unsigned offset); | |
76 | + void (*free)(struct gpio_chip *chip, | |
77 | + unsigned offset); | |
69 | 78 | |
70 | 79 | int (*direction_input)(struct gpio_chip *chip, |
71 | 80 | unsigned offset); |