diff options
Diffstat (limited to 'drivers/gpio/gpio-mmio.c')
-rw-r--r-- | drivers/gpio/gpio-mmio.c | 130 |
1 files changed, 102 insertions, 28 deletions
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index f7da40e46c55..f9042bcc27a4 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c | |||
@@ -126,20 +126,16 @@ static unsigned long bgpio_read32be(void __iomem *reg) | |||
126 | return ioread32be(reg); | 126 | return ioread32be(reg); |
127 | } | 127 | } |
128 | 128 | ||
129 | static unsigned long bgpio_pin2mask(struct gpio_chip *gc, unsigned int pin) | 129 | static unsigned long bgpio_line2mask(struct gpio_chip *gc, unsigned int line) |
130 | { | 130 | { |
131 | return BIT(pin); | 131 | if (gc->be_bits) |
132 | } | 132 | return BIT(gc->bgpio_bits - 1 - line); |
133 | 133 | return BIT(line); | |
134 | static unsigned long bgpio_pin2mask_be(struct gpio_chip *gc, | ||
135 | unsigned int pin) | ||
136 | { | ||
137 | return BIT(gc->bgpio_bits - 1 - pin); | ||
138 | } | 134 | } |
139 | 135 | ||
140 | static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) | 136 | static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) |
141 | { | 137 | { |
142 | unsigned long pinmask = gc->pin2mask(gc, gpio); | 138 | unsigned long pinmask = bgpio_line2mask(gc, gpio); |
143 | 139 | ||
144 | if (gc->bgpio_dir & pinmask) | 140 | if (gc->bgpio_dir & pinmask) |
145 | return !!(gc->read_reg(gc->reg_set) & pinmask); | 141 | return !!(gc->read_reg(gc->reg_set) & pinmask); |
@@ -147,9 +143,76 @@ static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio) | |||
147 | return !!(gc->read_reg(gc->reg_dat) & pinmask); | 143 | return !!(gc->read_reg(gc->reg_dat) & pinmask); |
148 | } | 144 | } |
149 | 145 | ||
146 | /* | ||
147 | * This assumes that the bits in the GPIO register are in native endianness. | ||
148 | * We only assign the function pointer if we have that. | ||
149 | */ | ||
150 | static int bgpio_get_set_multiple(struct gpio_chip *gc, unsigned long *mask, | ||
151 | unsigned long *bits) | ||
152 | { | ||
153 | unsigned long get_mask = 0; | ||
154 | unsigned long set_mask = 0; | ||
155 | int bit = 0; | ||
156 | |||
157 | while ((bit = find_next_bit(mask, gc->ngpio, bit)) != gc->ngpio) { | ||
158 | if (gc->bgpio_dir & BIT(bit)) | ||
159 | set_mask |= BIT(bit); | ||
160 | else | ||
161 | get_mask |= BIT(bit); | ||
162 | } | ||
163 | |||
164 | if (set_mask) | ||
165 | *bits |= gc->read_reg(gc->reg_set) & set_mask; | ||
166 | if (get_mask) | ||
167 | *bits |= gc->read_reg(gc->reg_dat) & get_mask; | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
150 | static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) | 172 | static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) |
151 | { | 173 | { |
152 | return !!(gc->read_reg(gc->reg_dat) & gc->pin2mask(gc, gpio)); | 174 | return !!(gc->read_reg(gc->reg_dat) & bgpio_line2mask(gc, gpio)); |
175 | } | ||
176 | |||
177 | /* | ||
178 | * 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 | */ | ||
181 | static int bgpio_get_multiple(struct gpio_chip *gc, unsigned long *mask, | ||
182 | unsigned long *bits) | ||
183 | { | ||
184 | |||
185 | *bits = gc->read_reg(gc->reg_dat) & *mask; | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * With big endian mirrored bit order it becomes more tedious. | ||
191 | */ | ||
192 | static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask, | ||
193 | unsigned long *bits) | ||
194 | { | ||
195 | unsigned long readmask = 0; | ||
196 | unsigned long val; | ||
197 | int bit; | ||
198 | |||
199 | /* Create a mirrored mask */ | ||
200 | bit = 0; | ||
201 | while ((bit = find_next_bit(mask, gc->ngpio, bit)) != gc->ngpio) | ||
202 | readmask |= bgpio_line2mask(gc, bit); | ||
203 | |||
204 | /* Read the register */ | ||
205 | val = gc->read_reg(gc->reg_dat) & readmask; | ||
206 | |||
207 | /* | ||
208 | * 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. | ||
210 | */ | ||
211 | bit = 0; | ||
212 | while ((bit = find_next_bit(&val, gc->ngpio, bit)) != gc->ngpio) | ||
213 | *bits |= bgpio_line2mask(gc, bit); | ||
214 | |||
215 | return 0; | ||
153 | } | 216 | } |
154 | 217 | ||
155 | static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) | 218 | static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) |
@@ -158,7 +221,7 @@ static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val) | |||
158 | 221 | ||
159 | static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | 222 | static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) |
160 | { | 223 | { |
161 | unsigned long mask = gc->pin2mask(gc, gpio); | 224 | unsigned long mask = bgpio_line2mask(gc, gpio); |
162 | unsigned long flags; | 225 | unsigned long flags; |
163 | 226 | ||
164 | spin_lock_irqsave(&gc->bgpio_lock, flags); | 227 | spin_lock_irqsave(&gc->bgpio_lock, flags); |
@@ -176,7 +239,7 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | |||
176 | static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, | 239 | static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, |
177 | int val) | 240 | int val) |
178 | { | 241 | { |
179 | unsigned long mask = gc->pin2mask(gc, gpio); | 242 | unsigned long mask = bgpio_line2mask(gc, gpio); |
180 | 243 | ||
181 | if (val) | 244 | if (val) |
182 | gc->write_reg(gc->reg_set, mask); | 245 | gc->write_reg(gc->reg_set, mask); |
@@ -186,7 +249,7 @@ static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio, | |||
186 | 249 | ||
187 | static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) | 250 | static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val) |
188 | { | 251 | { |
189 | unsigned long mask = gc->pin2mask(gc, gpio); | 252 | unsigned long mask = bgpio_line2mask(gc, gpio); |
190 | unsigned long flags; | 253 | unsigned long flags; |
191 | 254 | ||
192 | spin_lock_irqsave(&gc->bgpio_lock, flags); | 255 | spin_lock_irqsave(&gc->bgpio_lock, flags); |
@@ -216,9 +279,9 @@ static void bgpio_multiple_get_masks(struct gpio_chip *gc, | |||
216 | break; | 279 | break; |
217 | if (__test_and_clear_bit(i, mask)) { | 280 | if (__test_and_clear_bit(i, mask)) { |
218 | if (test_bit(i, bits)) | 281 | if (test_bit(i, bits)) |
219 | *set_mask |= gc->pin2mask(gc, i); | 282 | *set_mask |= bgpio_line2mask(gc, i); |
220 | else | 283 | else |
221 | *clear_mask |= gc->pin2mask(gc, i); | 284 | *clear_mask |= bgpio_line2mask(gc, i); |
222 | } | 285 | } |
223 | } | 286 | } |
224 | } | 287 | } |
@@ -294,7 +357,7 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | |||
294 | 357 | ||
295 | spin_lock_irqsave(&gc->bgpio_lock, flags); | 358 | spin_lock_irqsave(&gc->bgpio_lock, flags); |
296 | 359 | ||
297 | gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); | 360 | gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); |
298 | gc->write_reg(gc->reg_dir, gc->bgpio_dir); | 361 | gc->write_reg(gc->reg_dir, gc->bgpio_dir); |
299 | 362 | ||
300 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); | 363 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
@@ -305,7 +368,7 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | |||
305 | static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) | 368 | static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) |
306 | { | 369 | { |
307 | /* Return 0 if output, 1 of input */ | 370 | /* Return 0 if output, 1 of input */ |
308 | return !(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); | 371 | return !(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); |
309 | } | 372 | } |
310 | 373 | ||
311 | static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | 374 | static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
@@ -316,7 +379,7 @@ static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | |||
316 | 379 | ||
317 | spin_lock_irqsave(&gc->bgpio_lock, flags); | 380 | spin_lock_irqsave(&gc->bgpio_lock, flags); |
318 | 381 | ||
319 | gc->bgpio_dir |= gc->pin2mask(gc, gpio); | 382 | gc->bgpio_dir |= bgpio_line2mask(gc, gpio); |
320 | gc->write_reg(gc->reg_dir, gc->bgpio_dir); | 383 | gc->write_reg(gc->reg_dir, gc->bgpio_dir); |
321 | 384 | ||
322 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); | 385 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
@@ -330,7 +393,7 @@ static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio) | |||
330 | 393 | ||
331 | spin_lock_irqsave(&gc->bgpio_lock, flags); | 394 | spin_lock_irqsave(&gc->bgpio_lock, flags); |
332 | 395 | ||
333 | gc->bgpio_dir |= gc->pin2mask(gc, gpio); | 396 | gc->bgpio_dir |= bgpio_line2mask(gc, gpio); |
334 | gc->write_reg(gc->reg_dir, gc->bgpio_dir); | 397 | gc->write_reg(gc->reg_dir, gc->bgpio_dir); |
335 | 398 | ||
336 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); | 399 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
@@ -346,7 +409,7 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) | |||
346 | 409 | ||
347 | spin_lock_irqsave(&gc->bgpio_lock, flags); | 410 | spin_lock_irqsave(&gc->bgpio_lock, flags); |
348 | 411 | ||
349 | gc->bgpio_dir &= ~gc->pin2mask(gc, gpio); | 412 | gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); |
350 | gc->write_reg(gc->reg_dir, gc->bgpio_dir); | 413 | gc->write_reg(gc->reg_dir, gc->bgpio_dir); |
351 | 414 | ||
352 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); | 415 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
@@ -357,12 +420,11 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val) | |||
357 | static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio) | 420 | static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio) |
358 | { | 421 | { |
359 | /* Return 0 if output, 1 if input */ | 422 | /* Return 0 if output, 1 if input */ |
360 | return !!(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio)); | 423 | return !!(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); |
361 | } | 424 | } |
362 | 425 | ||
363 | static int bgpio_setup_accessors(struct device *dev, | 426 | static int bgpio_setup_accessors(struct device *dev, |
364 | struct gpio_chip *gc, | 427 | struct gpio_chip *gc, |
365 | bool bit_be, | ||
366 | bool byte_be) | 428 | bool byte_be) |
367 | { | 429 | { |
368 | 430 | ||
@@ -406,8 +468,6 @@ static int bgpio_setup_accessors(struct device *dev, | |||
406 | return -EINVAL; | 468 | return -EINVAL; |
407 | } | 469 | } |
408 | 470 | ||
409 | gc->pin2mask = bit_be ? bgpio_pin2mask_be : bgpio_pin2mask; | ||
410 | |||
411 | return 0; | 471 | return 0; |
412 | } | 472 | } |
413 | 473 | ||
@@ -462,10 +522,24 @@ static int bgpio_setup_io(struct gpio_chip *gc, | |||
462 | } | 522 | } |
463 | 523 | ||
464 | if (!(flags & BGPIOF_UNREADABLE_REG_SET) && | 524 | if (!(flags & BGPIOF_UNREADABLE_REG_SET) && |
465 | (flags & BGPIOF_READ_OUTPUT_REG_SET)) | 525 | (flags & BGPIOF_READ_OUTPUT_REG_SET)) { |
466 | gc->get = bgpio_get_set; | 526 | gc->get = bgpio_get_set; |
467 | else | 527 | if (!gc->be_bits) |
528 | gc->get_multiple = bgpio_get_set_multiple; | ||
529 | /* | ||
530 | * We deliberately avoid assigning the ->get_multiple() call | ||
531 | * for big endian mirrored registers which are ALSO reflecting | ||
532 | * their value in the set register when used as output. It is | ||
533 | * simply too much complexity, let the GPIO core fall back to | ||
534 | * reading each line individually in that fringe case. | ||
535 | */ | ||
536 | } else { | ||
468 | gc->get = bgpio_get; | 537 | gc->get = bgpio_get; |
538 | if (gc->be_bits) | ||
539 | gc->get_multiple = bgpio_get_multiple_be; | ||
540 | else | ||
541 | gc->get_multiple = bgpio_get_multiple; | ||
542 | } | ||
469 | 543 | ||
470 | return 0; | 544 | return 0; |
471 | } | 545 | } |
@@ -526,13 +600,13 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, | |||
526 | gc->base = -1; | 600 | gc->base = -1; |
527 | gc->ngpio = gc->bgpio_bits; | 601 | gc->ngpio = gc->bgpio_bits; |
528 | gc->request = bgpio_request; | 602 | gc->request = bgpio_request; |
603 | gc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN); | ||
529 | 604 | ||
530 | ret = bgpio_setup_io(gc, dat, set, clr, flags); | 605 | ret = bgpio_setup_io(gc, dat, set, clr, flags); |
531 | if (ret) | 606 | if (ret) |
532 | return ret; | 607 | return ret; |
533 | 608 | ||
534 | ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN, | 609 | ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); |
535 | flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); | ||
536 | if (ret) | 610 | if (ret) |
537 | return ret; | 611 | return ret; |
538 | 612 | ||