Commit 169b6a7a6e91e1ea32136681b475cbaf2074bf35

Authored by Anton Vorontsov
Committed by Linus Torvalds
1 parent 8d0aab2f16

gpiochip_reserve()

Add a new function gpiochip_reserve() to reserve ranges of gpios that platform
code has pre-allocated.  That is, this marks gpio numbers which will be
claimed by drivers that haven't yet been loaded, and thus are not available
for dynamic gpio number allocation.

[akpm@linux-foundation.org: remove unneeded __must_check]
[david-b@pacbell.net: don't export gpiochip_reserve (section fix)]
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 48 additions and 3 deletions Side-by-side Diff

drivers/gpio/gpiolib.c
... ... @@ -43,6 +43,7 @@
43 43 /* flag symbols are bit numbers */
44 44 #define FLAG_REQUESTED 0
45 45 #define FLAG_IS_OUT 1
  46 +#define FLAG_RESERVED 2
46 47  
47 48 #ifdef CONFIG_DEBUG_FS
48 49 const char *label;
49 50  
... ... @@ -88,9 +89,10 @@
88 89 int base = -ENOSPC;
89 90  
90 91 for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) {
91   - struct gpio_chip *chip = gpio_desc[i].chip;
  92 + struct gpio_desc *desc = &gpio_desc[i];
  93 + struct gpio_chip *chip = desc->chip;
92 94  
93   - if (!chip) {
  95 + if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) {
94 96 spare++;
95 97 if (spare == ngpio) {
96 98 base = i;
97 99  
... ... @@ -98,13 +100,55 @@
98 100 }
99 101 } else {
100 102 spare = 0;
101   - i -= chip->ngpio - 1;
  103 + if (chip)
  104 + i -= chip->ngpio - 1;
102 105 }
103 106 }
104 107  
105 108 if (gpio_is_valid(base))
106 109 pr_debug("%s: found new base at %d\n", __func__, base);
107 110 return base;
  111 +}
  112 +
  113 +/**
  114 + * gpiochip_reserve() - reserve range of gpios to use with platform code only
  115 + * @start: starting gpio number
  116 + * @ngpio: number of gpios to reserve
  117 + * Context: platform init, potentially before irqs or kmalloc will work
  118 + *
  119 + * Returns a negative errno if any gpio within the range is already reserved
  120 + * or registered, else returns zero as a success code. Use this function
  121 + * to mark a range of gpios as unavailable for dynamic gpio number allocation,
  122 + * for example because its driver support is not yet loaded.
  123 + */
  124 +int __init gpiochip_reserve(int start, int ngpio)
  125 +{
  126 + int ret = 0;
  127 + unsigned long flags;
  128 + int i;
  129 +
  130 + if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio))
  131 + return -EINVAL;
  132 +
  133 + spin_lock_irqsave(&gpio_lock, flags);
  134 +
  135 + for (i = start; i < start + ngpio; i++) {
  136 + struct gpio_desc *desc = &gpio_desc[i];
  137 +
  138 + if (desc->chip || test_bit(FLAG_RESERVED, &desc->flags)) {
  139 + ret = -EBUSY;
  140 + goto err;
  141 + }
  142 +
  143 + set_bit(FLAG_RESERVED, &desc->flags);
  144 + }
  145 +
  146 + pr_debug("%s: reserved gpios from %d to %d\n",
  147 + __func__, start, start + ngpio - 1);
  148 +err:
  149 + spin_unlock_irqrestore(&gpio_lock, flags);
  150 +
  151 + return ret;
108 152 }
109 153  
110 154 /**
include/asm-generic/gpio.h
... ... @@ -74,6 +74,7 @@
74 74  
75 75 extern const char *gpiochip_is_requested(struct gpio_chip *chip,
76 76 unsigned offset);
  77 +extern int __init __must_check gpiochip_reserve(int start, int ngpio);
77 78  
78 79 /* add/remove chips */
79 80 extern int gpiochip_add(struct gpio_chip *chip);