diff options
Diffstat (limited to 'drivers/gpio/gpio-mmio.c')
-rw-r--r-- | drivers/gpio/gpio-mmio.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index f9042bcc27a4..7b14d6280e44 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c | |||
@@ -152,14 +152,13 @@ static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask, | |||
152 | { | 152 | { |
153 | unsigned long get_mask = 0; | 153 | unsigned long get_mask = 0; |
154 | unsigned long set_mask = 0; | 154 | unsigned long set_mask = 0; |
155 | int bit = 0; | ||
156 | 155 | ||
157 | while ((bit = find_next_bit(mask, gc->ngpio, bit)) != gc->ngpio) { | 156 | /* Make sure we first clear any bits that are zero when we read the register */ |
158 | if (gc->bgpio_dir & BIT(bit)) | 157 | *bits &= ~*mask; |
159 | set_mask |= BIT(bit); | 158 | |
160 | else | 159 | /* Exploit the fact that we know which directions are set */ |
161 | get_mask |= BIT(bit); | 160 | set_mask = *mask & gc->bgpio_dir; |
162 | } | 161 | get_mask = *mask & ~gc->bgpio_dir; |
163 | 162 | ||
164 | if (set_mask) | 163 | if (set_mask) |
165 | *bits |= gc->read_reg(gc->reg_set) & set_mask; | 164 | *bits |= gc->read_reg(gc->reg_set) & set_mask; |
@@ -176,13 +175,13 @@ static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) | |||
176 | 175 | ||
177 | /* | 176 | /* |
178 | * This only works if the bits in the GPIO register are in native endianness. | 177 | * This only works if the bits in the GPIO register are in native endianness. |
179 | * It is dirt simple and fast in this case. (Also the most common case.) | ||
180 | */ | 178 | */ |
181 | static int bgpio_get_multiple(struct gpio_chip *gc, unsigned long *mask, | 179 | static int bgpio_get_multiple(struct gpio_chip *gc, unsigned long *mask, |
182 | unsigned long *bits) | 180 | unsigned long *bits) |
183 | { | 181 | { |
184 | 182 | /* Make sure we first clear any bits that are zero when we read the register */ | |
185 | *bits = gc->read_reg(gc->reg_dat) & *mask; | 183 | *bits &= ~*mask; |
184 | *bits |= gc->read_reg(gc->reg_dat) & *mask; | ||
186 | return 0; | 185 | return 0; |
187 | } | 186 | } |
188 | 187 | ||
@@ -196,9 +195,12 @@ static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask, | |||
196 | unsigned long val; | 195 | unsigned long val; |
197 | int bit; | 196 | int bit; |
198 | 197 | ||
198 | /* Make sure we first clear any bits that are zero when we read the register */ | ||
199 | *bits &= ~*mask; | ||
200 | |||
199 | /* Create a mirrored mask */ | 201 | /* Create a mirrored mask */ |
200 | bit = 0; | 202 | bit = -1; |
201 | while ((bit = find_next_bit(mask, gc->ngpio, bit)) != gc->ngpio) | 203 | while ((bit = find_next_bit(mask, gc->ngpio, bit + 1)) < gc->ngpio) |
202 | readmask |= bgpio_line2mask(gc, bit); | 204 | readmask |= bgpio_line2mask(gc, bit); |
203 | 205 | ||
204 | /* Read the register */ | 206 | /* Read the register */ |
@@ -208,8 +210,8 @@ static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask, | |||
208 | * Mirror the result into the "bits" result, this will give line 0 | 210 | * Mirror the result into the "bits" result, this will give line 0 |
209 | * in bit 0 ... line 31 in bit 31 for a 32bit register. | 211 | * in bit 0 ... line 31 in bit 31 for a 32bit register. |
210 | */ | 212 | */ |
211 | bit = 0; | 213 | bit = -1; |
212 | while ((bit = find_next_bit(&val, gc->ngpio, bit)) != gc->ngpio) | 214 | while ((bit = find_next_bit(&val, gc->ngpio, bit + 1)) < gc->ngpio) |
213 | *bits |= bgpio_line2mask(gc, bit); | 215 | *bits |= bgpio_line2mask(gc, bit); |
214 | 216 | ||
215 | return 0; | 217 | return 0; |