[PATCH] gpiolib: implement dynamic base allocation

From: Anton Vorontsov
Date: Tue Mar 04 2008 - 12:03:22 EST


If gpio_chip->base is negative during registration, gpiolib requests
dynamic base allocation. This is useful for devices being registered
at run-time (in contrast to platform devices).

Signed-off-by: Anton Vorontsov <avorontsov@xxxxxxxxxxxxx>
---
drivers/gpio/gpiolib.c | 42 ++++++++++++++++++++++++++++++++++++------
1 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index d8db2f8..1d25104 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -77,6 +77,32 @@ static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
return gpio_desc[gpio].chip;
}

+static int gpiochip_find_base(int ngpio)
+{
+ int i;
+ int spare = 0;
+ int next_base = 0;
+ int base = -ENOSPC;
+
+ for (i = 0; i < ARCH_NR_GPIOS; i++) {
+ struct gpio_chip *c = gpio_desc[i].chip;
+
+ if (!c) {
+ spare++;
+ if (spare == ngpio) {
+ base = next_base;
+ break;
+ }
+ } else {
+ spare = 0;
+ i += c->ngpio;
+ next_base = i;
+ }
+ }
+
+ return base;
+}
+
/**
* gpiochip_add() - register a gpio_chip
* @chip: the chip to register, with chip->base initialized
@@ -92,17 +118,21 @@ int gpiochip_add(struct gpio_chip *chip)
int status = 0;
unsigned id;

- /* NOTE chip->base negative is reserved to mean a request for
- * dynamic allocation. We don't currently support that.
- */
-
- if (chip->base < 0 || (chip->base + chip->ngpio) >= ARCH_NR_GPIOS) {
+ if (chip->base >= 0 && chip->base + chip->ngpio >= ARCH_NR_GPIOS) {
status = -EINVAL;
goto fail;
}

spin_lock_irqsave(&gpio_lock, flags);

+ if (chip->base < 0) {
+ chip->base = gpiochip_find_base(chip->ngpio);
+ if (chip->base < 0) {
+ status = chip->base;
+ goto fail_unlock;
+ }
+ }
+
/* these GPIO numbers must not be managed by another gpio_chip */
for (id = chip->base; id < chip->base + chip->ngpio; id++) {
if (gpio_desc[id].chip != NULL) {
@@ -116,7 +146,7 @@ int gpiochip_add(struct gpio_chip *chip)
gpio_desc[id].flags = 0;
}
}
-
+fail_unlock:
spin_unlock_irqrestore(&gpio_lock, flags);
fail:
/* failures here can mean systems won't boot... */
--
1.5.2.2
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/