aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/gpiolib.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 2ba6127c4fae..24c62b848bf9 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -43,6 +43,7 @@ struct gpio_desc {
43/* flag symbols are bit numbers */ 43/* flag symbols are bit numbers */
44#define FLAG_REQUESTED 0 44#define FLAG_REQUESTED 0
45#define FLAG_IS_OUT 1 45#define FLAG_IS_OUT 1
46#define FLAG_RESERVED 2
46 47
47#ifdef CONFIG_DEBUG_FS 48#ifdef CONFIG_DEBUG_FS
48 const char *label; 49 const char *label;
@@ -88,9 +89,10 @@ static int gpiochip_find_base(int ngpio)
88 int base = -ENOSPC; 89 int base = -ENOSPC;
89 90
90 for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) { 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 spare++; 96 spare++;
95 if (spare == ngpio) { 97 if (spare == ngpio) {
96 base = i; 98 base = i;
@@ -98,7 +100,8 @@ static int gpiochip_find_base(int ngpio)
98 } 100 }
99 } else { 101 } else {
100 spare = 0; 102 spare = 0;
101 i -= chip->ngpio - 1; 103 if (chip)
104 i -= chip->ngpio - 1;
102 } 105 }
103 } 106 }
104 107
@@ -108,6 +111,47 @@ static int gpiochip_find_base(int ngpio)
108} 111}
109 112
110/** 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 */
124int __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);
148err:
149 spin_unlock_irqrestore(&gpio_lock, flags);
150
151 return ret;
152}
153
154/**
111 * gpiochip_add() - register a gpio_chip 155 * gpiochip_add() - register a gpio_chip
112 * @chip: the chip to register, with chip->base initialized 156 * @chip: the chip to register, with chip->base initialized
113 * Context: potentially before irqs or kmalloc will work 157 * Context: potentially before irqs or kmalloc will work