[s3c24xx] jbt6k74: Change the state machine to have one state field for
[openwrt.git] / target / linux / generic-2.6 / patches-2.6.25 / 962-backport_gpiolib_dynamic_gpio_number_allocation.patch
1 From: Anton Vorontsov <avorontsov@ru.mvista.com>
2 Date: Mon, 28 Apr 2008 09:14:46 +0000 (-0700)
3 Subject: gpiolib: dynamic gpio number allocation
4 X-Git-Tag: v2.6.26-rc1~848
5 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=8d0aab2f16c4fa170f32e7a74a52cd0122bbafef
6
7 gpiolib: dynamic gpio number allocation
8
9 If gpio_chip->base is negative during registration, gpiolib performs dynamic
10 base allocation. This is useful for devices that aren't always present, such
11 as GPIOs on hotplugged devices rather than mainboards. (This behavior was
12 previously specified but not implemented.)
13
14 To avoid using any numbers that may have been explicitly assigned but not yet
15 registered, this dynamic allocation assigns GPIO numbers from the biggest
16 number on down, instead of from the smallest on up.
17
18 Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
19 Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
20 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
21 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
22 ---
23
24 --- a/drivers/gpio/gpiolib.c
25 +++ b/drivers/gpio/gpiolib.c
26 @@ -80,6 +80,33 @@ static inline struct gpio_chip *gpio_to_
27 return gpio_desc[gpio].chip;
28 }
29
30 +/* dynamic allocation of GPIOs, e.g. on a hotplugged device */
31 +static int gpiochip_find_base(int ngpio)
32 +{
33 + int i;
34 + int spare = 0;
35 + int base = -ENOSPC;
36 +
37 + for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) {
38 + struct gpio_chip *chip = gpio_desc[i].chip;
39 +
40 + if (!chip) {
41 + spare++;
42 + if (spare == ngpio) {
43 + base = i;
44 + break;
45 + }
46 + } else {
47 + spare = 0;
48 + i -= chip->ngpio - 1;
49 + }
50 + }
51 +
52 + if (gpio_is_valid(base))
53 + pr_debug("%s: found new base at %d\n", __func__, base);
54 + return base;
55 +}
56 +
57 /**
58 * gpiochip_add() - register a gpio_chip
59 * @chip: the chip to register, with chip->base initialized
60 @@ -88,38 +115,49 @@ static inline struct gpio_chip *gpio_to_
61 * Returns a negative errno if the chip can't be registered, such as
62 * because the chip->base is invalid or already associated with a
63 * different chip. Otherwise it returns zero as a success code.
64 + *
65 + * If chip->base is negative, this requests dynamic assignment of
66 + * a range of valid GPIOs.
67 */
68 int gpiochip_add(struct gpio_chip *chip)
69 {
70 unsigned long flags;
71 int status = 0;
72 unsigned id;
73 + int base = chip->base;
74
75 - /* NOTE chip->base negative is reserved to mean a request for
76 - * dynamic allocation. We don't currently support that.
77 - */
78 -
79 - if (chip->base < 0 || !gpio_is_valid(chip->base + chip->ngpio)) {
80 + if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio))
81 + && base >= 0) {
82 status = -EINVAL;
83 goto fail;
84 }
85
86 spin_lock_irqsave(&gpio_lock, flags);
87
88 + if (base < 0) {
89 + base = gpiochip_find_base(chip->ngpio);
90 + if (base < 0) {
91 + status = base;
92 + goto fail_unlock;
93 + }
94 + chip->base = base;
95 + }
96 +
97 /* these GPIO numbers must not be managed by another gpio_chip */
98 - for (id = chip->base; id < chip->base + chip->ngpio; id++) {
99 + for (id = base; id < base + chip->ngpio; id++) {
100 if (gpio_desc[id].chip != NULL) {
101 status = -EBUSY;
102 break;
103 }
104 }
105 if (status == 0) {
106 - for (id = chip->base; id < chip->base + chip->ngpio; id++) {
107 + for (id = base; id < base + chip->ngpio; id++) {
108 gpio_desc[id].chip = chip;
109 gpio_desc[id].flags = 0;
110 }
111 }
112
113 +fail_unlock:
114 spin_unlock_irqrestore(&gpio_lock, flags);
115 fail:
116 /* failures here can mean systems won't boot... */
This page took 0.051119 seconds and 5 git commands to generate.