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
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
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;
35 - /* Too bad we don't have committable items... */
38 struct pio_device *pio;
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)
52 - return sprintf(page, "%u\n", pio_id(gpio->pio));
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
62 if ((id < MAX_NR_PIO_DEVICES) && pio_dev[id].regs) {
63 - gpio->pio = &pio_dev[id];
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;
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')))
84 - * Must have a PIO before we can start allocating pins, but we
87 + /* Can't update the pin mask while live. */
88 spin_lock(&gpio->lock);
90 - if (!pio || gpio->enabled)
94 - old_mask = gpio->pin_mask;
96 - old = pio->pinmux_mask;
97 - if ((old & ~old_mask) & new_mask)
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);
109 + if (!gpio->enabled) {
110 + gpio->oe_mask &= new_mask;
111 + gpio->pin_mask = new_mask;
114 spin_unlock(&gpio->lock);
119 static ssize_t gpio_show_oe_mask(struct gpio_item *gpio, char *page)
123 - spin_lock(&gpio->lock);
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
138 spin_lock(&gpio->lock);
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;
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;
154 char *p = (char *)page;
157 @@ -482,6 +445,12 @@ static ssize_t gpio_store_enabled(struct
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);
165 + if (gpio->pio_id < 0 || !gpio->pin_mask)
169 /* Disallow any updates to gpio_id or pin_mask */
170 @@ -492,6 +461,20 @@ static ssize_t gpio_store_enabled(struct
174 + /* Now, try to allocate the pins */
176 + pio = gpio->pio = &pio_dev[gpio->pio_id];
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
193 cdev_del(&gpio->char_dev);
195 + __disable_gpio(pio, gpio->pin_mask);
196 + pio_dealloc_mask(pio, gpio->pin_mask);
198 spin_lock(&gpio->lock);
200 spin_unlock(&gpio->lock);