linux-omap 2.6.37: replace various patch with upstream versions and rediff
[openembedded.git] / recipes / linux / linux-2.6.18 / gpio-dev-robustness.patch
blob56ef0ebc6c0a62d636f7f2d743e509d54124ae25
1 Make the GPIO /dev interface a bit more robust
3 Instead of allocating gpio resources on-the-fly as the files are
4 written, defer it until enable is set to 1 and disallow updates to
5 any of the other files while enable=1.
7 Otherwise, the number of checks in each _store function will rapidly
8 approach insanity.
9 ---
10 arch/avr32/mach-at32ap/pio.c | 99 ++++++++++++++++++-------------------------
11 1 file changed, 43 insertions(+), 56 deletions(-)
13 Index: linux-2.6.18-avr32/arch/avr32/mach-at32ap/pio.c
14 ===================================================================
15 --- linux-2.6.18-avr32.orig/arch/avr32/mach-at32ap/pio.c 2006-11-29 17:10:54.000000000 +0100
16 +++ linux-2.6.18-avr32/arch/avr32/mach-at32ap/pio.c 2006-11-29 18:11:38.000000000 +0100
17 @@ -124,13 +124,6 @@ static unsigned int pio_id(struct pio_de
18 return pio - pio_dev;
21 -static void __enable_gpio(struct pio_device *pio, u32 mask)
23 - pio_writel(pio, PUER, mask);
24 - pio_writel(pio, ODR, mask);
25 - pio_writel(pio, PER, mask);
28 static void __disable_gpio(struct pio_device *pio, u32 mask)
30 pio_writel(pio, PUER, mask);
31 @@ -251,11 +244,12 @@ static dev_t gpio_devt;
32 struct gpio_item {
33 spinlock_t lock;
35 - /* Too bad we don't have committable items... */
36 - int enabled;
38 struct pio_device *pio;
40 + int enabled;
41 + int pio_id;
42 u32 pin_mask;
43 + u32 oe_mask;
45 int id;
46 struct class_device *gpio_dev;
47 @@ -339,10 +333,7 @@ static struct gpio_item *to_gpio_item(st
49 static ssize_t gpio_show_gpio_id(struct gpio_item *gpio, char *page)
51 - if (gpio->pio)
52 - return sprintf(page, "%u\n", pio_id(gpio->pio));
53 - else
54 - return sprintf(page, "-1\n");
55 + return sprintf(page, "%d\n", gpio->pio_id);
58 static ssize_t gpio_store_gpio_id(struct gpio_item *gpio,
59 @@ -361,7 +352,7 @@ static ssize_t gpio_store_gpio_id(struct
60 if (!gpio->enabled) {
61 ret = -ENXIO;
62 if ((id < MAX_NR_PIO_DEVICES) && pio_dev[id].regs) {
63 - gpio->pio = &pio_dev[id];
64 + gpio->pio_id = id;
65 ret = count;
68 @@ -378,9 +369,7 @@ static ssize_t gpio_show_pin_mask(struct
69 static ssize_t gpio_store_pin_mask(struct gpio_item *gpio,
70 const char *page, size_t count)
72 - struct pio_device *pio;
73 - u32 old_mask, new_mask;
74 - u32 old, new;
75 + u32 new_mask;
76 char *p = (char *)page;
77 ssize_t ret = -EINVAL;
79 @@ -388,47 +377,21 @@ static ssize_t gpio_store_pin_mask(struc
80 if (!p || (*p && (*p != '\n')))
81 return -EINVAL;
83 - /*
84 - * Must have a PIO before we can start allocating pins, but we
85 - * must not be live.
86 - */
87 + /* Can't update the pin mask while live. */
88 spin_lock(&gpio->lock);
89 - pio = gpio->pio;
90 - if (!pio || gpio->enabled)
91 - goto out;
93 - ret = -EBUSY;
94 - old_mask = gpio->pin_mask;
95 - do {
96 - old = pio->pinmux_mask;
97 - if ((old & ~old_mask) & new_mask)
98 - goto out;
100 - new = (old & ~old_mask) | new_mask;
101 - } while (cmpxchg(&pio->pinmux_mask, old, new) != old);
103 - gpio->pin_mask = new_mask;
104 - __disable_gpio(pio, old_mask);
105 - __enable_gpio(pio, new_mask);
106 - ret = count;
108 -out:
109 + if (!gpio->enabled) {
110 + gpio->oe_mask &= new_mask;
111 + gpio->pin_mask = new_mask;
112 + ret = count;
114 spin_unlock(&gpio->lock);
116 return ret;
119 static ssize_t gpio_show_oe_mask(struct gpio_item *gpio, char *page)
121 - u32 mask = 0;
123 - spin_lock(&gpio->lock);
124 - if (gpio->pio) {
125 - mask = pio_readl(gpio->pio, OSR);
126 - mask &= gpio->pin_mask;
128 - spin_unlock(&gpio->lock);
130 - return sprintf(page, "0x%08x\n", mask);
131 + return sprintf(page, "0x%08x\n", gpio->oe_mask);
134 static ssize_t gpio_store_oe_mask(struct gpio_item *gpio,
135 @@ -443,10 +406,8 @@ static ssize_t gpio_store_oe_mask(struct
136 return -EINVAL;
138 spin_lock(&gpio->lock);
139 - if (gpio->pio) {
140 - mask &= gpio->pin_mask;
141 - pio_writel(gpio->pio, ODR, mask ^ gpio->pin_mask);
142 - pio_writel(gpio->pio, OER, mask);
143 + if (!gpio->enabled) {
144 + gpio->oe_mask = mask & gpio->pin_mask;
145 ret = count;
147 spin_unlock(&gpio->lock);
148 @@ -462,6 +423,8 @@ static ssize_t gpio_show_enabled(struct
149 static ssize_t gpio_store_enabled(struct gpio_item *gpio,
150 const char *page, size_t count)
152 + struct pio_device *pio;
153 + u32 old, new;
154 char *p = (char *)page;
155 int enabled;
156 int ret;
157 @@ -482,6 +445,12 @@ static ssize_t gpio_store_enabled(struct
158 if (!enabled) {
159 class_device_unregister(gpio->gpio_dev);
160 cdev_del(&gpio->char_dev);
161 + __disable_gpio(gpio->pio, gpio->pin_mask);
162 + pio_dealloc_mask(gpio->pio, gpio->pin_mask);
163 + gpio->pio = NULL;
164 + } else {
165 + if (gpio->pio_id < 0 || !gpio->pin_mask)
166 + return -ENODEV;
169 /* Disallow any updates to gpio_id or pin_mask */
170 @@ -492,6 +461,20 @@ static ssize_t gpio_store_enabled(struct
171 if (!enabled)
172 return count;
174 + /* Now, try to allocate the pins */
175 + ret = -EBUSY;
176 + pio = gpio->pio = &pio_dev[gpio->pio_id];
177 + do {
178 + old = pio->pinmux_mask;
179 + if (old & gpio->pin_mask)
180 + goto err_alloc_pins;
182 + new = old | gpio->pin_mask;
183 + } while (cmpxchg(&pio->pinmux_mask, old, new) != old);
185 + pio_writel(pio, OER, gpio->oe_mask);
186 + pio_writel(pio, PER, gpio->pin_mask);
188 cdev_init(&gpio->char_dev, &gpio_dev_fops);
189 gpio->char_dev.owner = THIS_MODULE;
190 ret = cdev_add(&gpio->char_dev, MKDEV(MAJOR(gpio_devt), gpio->id), 1);
191 @@ -516,9 +499,13 @@ static ssize_t gpio_store_enabled(struct
192 err_class_dev:
193 cdev_del(&gpio->char_dev);
194 err_cdev_add:
195 + __disable_gpio(pio, gpio->pin_mask);
196 + pio_dealloc_mask(pio, gpio->pin_mask);
197 +err_alloc_pins:
198 spin_lock(&gpio->lock);
199 gpio->enabled = 0;
200 spin_unlock(&gpio->lock);
201 + gpio->pio = NULL;
203 return ret;