[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20080304170307.GA29979@localhost.localdomain>
Date: Tue, 4 Mar 2008 20:03:07 +0300
From: Anton Vorontsov <avorontsov@...mvista.com>
To: David Brownell <dbrownell@...rs.sourceforge.net>
Cc: linux-kernel@...r.kernel.org
Subject: [PATCH] gpiolib: implement dynamic base allocation
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@...mvista.com>
---
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@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists