306fb0a1694de3ae4612b857b0f4c4fb49c2418b
[openwrt/svn-archive/archive.git] / target / linux / generic-2.6 / patches-2.6.25 / 963-backport_gpio_chip_reserve.patch
1 From: Anton Vorontsov <avorontsov@ru.mvista.com>
2 Date: Mon, 28 Apr 2008 09:14:47 +0000 (-0700)
3 Subject: gpiochip_reserve()
4 X-Git-Tag: v2.6.26-rc1~847
5 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=169b6a7a6e91e1ea32136681b475cbaf2074bf35
6
7 gpiochip_reserve()
8
9 Add a new function gpiochip_reserve() to reserve ranges of gpios that platform
10 code has pre-allocated. That is, this marks gpio numbers which will be
11 claimed by drivers that haven't yet been loaded, and thus are not available
12 for dynamic gpio number allocation.
13
14 [akpm@linux-foundation.org: remove unneeded __must_check]
15 [david-b@pacbell.net: don't export gpiochip_reserve (section fix)]
16 Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
17 Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
18 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
19 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
20 ---
21
22 diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
23 index 2ba6127..24c62b8 100644
24 --- a/drivers/gpio/gpiolib.c
25 +++ b/drivers/gpio/gpiolib.c
26 @@ -43,6 +43,7 @@ struct gpio_desc {
27 /* flag symbols are bit numbers */
28 #define FLAG_REQUESTED 0
29 #define FLAG_IS_OUT 1
30 +#define FLAG_RESERVED 2
31
32 #ifdef CONFIG_DEBUG_FS
33 const char *label;
34 @@ -88,9 +89,10 @@ static int gpiochip_find_base(int ngpio)
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 + struct gpio_desc *desc = &gpio_desc[i];
40 + struct gpio_chip *chip = desc->chip;
41
42 - if (!chip) {
43 + if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) {
44 spare++;
45 if (spare == ngpio) {
46 base = i;
47 @@ -98,7 +100,8 @@ static int gpiochip_find_base(int ngpio)
48 }
49 } else {
50 spare = 0;
51 - i -= chip->ngpio - 1;
52 + if (chip)
53 + i -= chip->ngpio - 1;
54 }
55 }
56
57 @@ -108,6 +111,47 @@ static int gpiochip_find_base(int ngpio)
58 }
59
60 /**
61 + * gpiochip_reserve() - reserve range of gpios to use with platform code only
62 + * @start: starting gpio number
63 + * @ngpio: number of gpios to reserve
64 + * Context: platform init, potentially before irqs or kmalloc will work
65 + *
66 + * Returns a negative errno if any gpio within the range is already reserved
67 + * or registered, else returns zero as a success code. Use this function
68 + * to mark a range of gpios as unavailable for dynamic gpio number allocation,
69 + * for example because its driver support is not yet loaded.
70 + */
71 +int __init gpiochip_reserve(int start, int ngpio)
72 +{
73 + int ret = 0;
74 + unsigned long flags;
75 + int i;
76 +
77 + if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio))
78 + return -EINVAL;
79 +
80 + spin_lock_irqsave(&gpio_lock, flags);
81 +
82 + for (i = start; i < start + ngpio; i++) {
83 + struct gpio_desc *desc = &gpio_desc[i];
84 +
85 + if (desc->chip || test_bit(FLAG_RESERVED, &desc->flags)) {
86 + ret = -EBUSY;
87 + goto err;
88 + }
89 +
90 + set_bit(FLAG_RESERVED, &desc->flags);
91 + }
92 +
93 + pr_debug("%s: reserved gpios from %d to %d\n",
94 + __func__, start, start + ngpio - 1);
95 +err:
96 + spin_unlock_irqrestore(&gpio_lock, flags);
97 +
98 + return ret;
99 +}
100 +
101 +/**
102 * gpiochip_add() - register a gpio_chip
103 * @chip: the chip to register, with chip->base initialized
104 * Context: potentially before irqs or kmalloc will work
105 diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
106 index 464c5b3..ecf675a 100644
107 --- a/include/asm-generic/gpio.h
108 +++ b/include/asm-generic/gpio.h
109 @@ -74,6 +74,7 @@ struct gpio_chip {
110
111 extern const char *gpiochip_is_requested(struct gpio_chip *chip,
112 unsigned offset);
113 +extern int __init __must_check gpiochip_reserve(int start, int ngpio);
114
115 /* add/remove chips */
116 extern int gpiochip_add(struct gpio_chip *chip);