.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
---|
1 | 2 | /* |
---|
2 | 3 | * Generic driver for memory-mapped GPIO controllers. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright 2008 MontaVista Software, Inc. |
---|
5 | 6 | * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify it |
---|
8 | | - * under the terms of the GNU General Public License as published by the |
---|
9 | | - * Free Software Foundation; either version 2 of the License, or (at your |
---|
10 | | - * option) any later version. |
---|
11 | 7 | * |
---|
12 | 8 | * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... |
---|
13 | 9 | * ...`` ```````.. |
---|
.. | .. |
---|
138 | 134 | unsigned long pinmask = bgpio_line2mask(gc, gpio); |
---|
139 | 135 | bool dir = !!(gc->bgpio_dir & pinmask); |
---|
140 | 136 | |
---|
141 | | - /* |
---|
142 | | - * If the direction is OUT we read the value from the SET |
---|
143 | | - * register, and if the direction is IN we read the value |
---|
144 | | - * from the DAT register. |
---|
145 | | - * |
---|
146 | | - * If the direction bits are inverted, naturally this gets |
---|
147 | | - * inverted too. |
---|
148 | | - */ |
---|
149 | | - if (gc->bgpio_dir_inverted) |
---|
150 | | - dir = !dir; |
---|
151 | | - |
---|
152 | 137 | if (dir) |
---|
153 | 138 | return !!(gc->read_reg(gc->reg_set) & pinmask); |
---|
154 | 139 | else |
---|
.. | .. |
---|
168 | 153 | /* Make sure we first clear any bits that are zero when we read the register */ |
---|
169 | 154 | *bits &= ~*mask; |
---|
170 | 155 | |
---|
171 | | - /* Exploit the fact that we know which directions are set */ |
---|
172 | | - if (gc->bgpio_dir_inverted) { |
---|
173 | | - set_mask = *mask & ~gc->bgpio_dir; |
---|
174 | | - get_mask = *mask & gc->bgpio_dir; |
---|
175 | | - } else { |
---|
176 | | - set_mask = *mask & gc->bgpio_dir; |
---|
177 | | - get_mask = *mask & ~gc->bgpio_dir; |
---|
178 | | - } |
---|
| 156 | + set_mask = *mask & gc->bgpio_dir; |
---|
| 157 | + get_mask = *mask & ~gc->bgpio_dir; |
---|
179 | 158 | |
---|
180 | 159 | if (set_mask) |
---|
181 | 160 | *bits |= gc->read_reg(gc->reg_set) & set_mask; |
---|
.. | .. |
---|
216 | 195 | *bits &= ~*mask; |
---|
217 | 196 | |
---|
218 | 197 | /* Create a mirrored mask */ |
---|
219 | | - bit = -1; |
---|
220 | | - while ((bit = find_next_bit(mask, gc->ngpio, bit + 1)) < gc->ngpio) |
---|
| 198 | + for_each_set_bit(bit, mask, gc->ngpio) |
---|
221 | 199 | readmask |= bgpio_line2mask(gc, bit); |
---|
222 | 200 | |
---|
223 | 201 | /* Read the register */ |
---|
.. | .. |
---|
227 | 205 | * Mirror the result into the "bits" result, this will give line 0 |
---|
228 | 206 | * in bit 0 ... line 31 in bit 31 for a 32bit register. |
---|
229 | 207 | */ |
---|
230 | | - bit = -1; |
---|
231 | | - while ((bit = find_next_bit(&val, gc->ngpio, bit + 1)) < gc->ngpio) |
---|
| 208 | + for_each_set_bit(bit, &val, gc->ngpio) |
---|
232 | 209 | *bits |= bgpio_line2mask(gc, bit); |
---|
233 | 210 | |
---|
234 | 211 | return 0; |
---|
.. | .. |
---|
293 | 270 | *set_mask = 0; |
---|
294 | 271 | *clear_mask = 0; |
---|
295 | 272 | |
---|
296 | | - for (i = 0; i < gc->bgpio_bits; i++) { |
---|
297 | | - if (*mask == 0) |
---|
298 | | - break; |
---|
299 | | - if (__test_and_clear_bit(i, mask)) { |
---|
300 | | - if (test_bit(i, bits)) |
---|
301 | | - *set_mask |= bgpio_line2mask(gc, i); |
---|
302 | | - else |
---|
303 | | - *clear_mask |= bgpio_line2mask(gc, i); |
---|
304 | | - } |
---|
| 273 | + for_each_set_bit(i, mask, gc->bgpio_bits) { |
---|
| 274 | + if (test_bit(i, bits)) |
---|
| 275 | + *set_mask |= bgpio_line2mask(gc, i); |
---|
| 276 | + else |
---|
| 277 | + *clear_mask |= bgpio_line2mask(gc, i); |
---|
305 | 278 | } |
---|
306 | 279 | } |
---|
307 | 280 | |
---|
.. | .. |
---|
376 | 349 | |
---|
377 | 350 | spin_lock_irqsave(&gc->bgpio_lock, flags); |
---|
378 | 351 | |
---|
379 | | - if (gc->bgpio_dir_inverted) |
---|
380 | | - gc->bgpio_dir |= bgpio_line2mask(gc, gpio); |
---|
381 | | - else |
---|
382 | | - gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); |
---|
383 | | - gc->write_reg(gc->reg_dir, gc->bgpio_dir); |
---|
| 352 | + gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); |
---|
| 353 | + |
---|
| 354 | + if (gc->reg_dir_in) |
---|
| 355 | + gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); |
---|
| 356 | + if (gc->reg_dir_out) |
---|
| 357 | + gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); |
---|
384 | 358 | |
---|
385 | 359 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
---|
386 | 360 | |
---|
.. | .. |
---|
389 | 363 | |
---|
390 | 364 | static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio) |
---|
391 | 365 | { |
---|
392 | | - /* Return 0 if output, 1 of input */ |
---|
393 | | - if (gc->bgpio_dir_inverted) |
---|
394 | | - return !!(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); |
---|
395 | | - else |
---|
396 | | - return !(gc->read_reg(gc->reg_dir) & bgpio_line2mask(gc, gpio)); |
---|
| 366 | + /* Return 0 if output, 1 if input */ |
---|
| 367 | + if (gc->bgpio_dir_unreadable) { |
---|
| 368 | + if (gc->bgpio_dir & bgpio_line2mask(gc, gpio)) |
---|
| 369 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 370 | + return GPIO_LINE_DIRECTION_IN; |
---|
| 371 | + } |
---|
| 372 | + |
---|
| 373 | + if (gc->reg_dir_out) { |
---|
| 374 | + if (gc->read_reg(gc->reg_dir_out) & bgpio_line2mask(gc, gpio)) |
---|
| 375 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 376 | + return GPIO_LINE_DIRECTION_IN; |
---|
| 377 | + } |
---|
| 378 | + |
---|
| 379 | + if (gc->reg_dir_in) |
---|
| 380 | + if (!(gc->read_reg(gc->reg_dir_in) & bgpio_line2mask(gc, gpio))) |
---|
| 381 | + return GPIO_LINE_DIRECTION_OUT; |
---|
| 382 | + |
---|
| 383 | + return GPIO_LINE_DIRECTION_IN; |
---|
397 | 384 | } |
---|
398 | 385 | |
---|
399 | | -static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
---|
| 386 | +static void bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
---|
400 | 387 | { |
---|
401 | 388 | unsigned long flags; |
---|
402 | 389 | |
---|
403 | | - gc->set(gc, gpio, val); |
---|
404 | | - |
---|
405 | 390 | spin_lock_irqsave(&gc->bgpio_lock, flags); |
---|
406 | 391 | |
---|
407 | | - if (gc->bgpio_dir_inverted) |
---|
408 | | - gc->bgpio_dir &= ~bgpio_line2mask(gc, gpio); |
---|
409 | | - else |
---|
410 | | - gc->bgpio_dir |= bgpio_line2mask(gc, gpio); |
---|
411 | | - gc->write_reg(gc->reg_dir, gc->bgpio_dir); |
---|
| 392 | + gc->bgpio_dir |= bgpio_line2mask(gc, gpio); |
---|
| 393 | + |
---|
| 394 | + if (gc->reg_dir_in) |
---|
| 395 | + gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); |
---|
| 396 | + if (gc->reg_dir_out) |
---|
| 397 | + gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); |
---|
412 | 398 | |
---|
413 | 399 | spin_unlock_irqrestore(&gc->bgpio_lock, flags); |
---|
| 400 | +} |
---|
414 | 401 | |
---|
| 402 | +static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio, |
---|
| 403 | + int val) |
---|
| 404 | +{ |
---|
| 405 | + bgpio_dir_out(gc, gpio, val); |
---|
| 406 | + gc->set(gc, gpio, val); |
---|
| 407 | + return 0; |
---|
| 408 | +} |
---|
| 409 | + |
---|
| 410 | +static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio, |
---|
| 411 | + int val) |
---|
| 412 | +{ |
---|
| 413 | + gc->set(gc, gpio, val); |
---|
| 414 | + bgpio_dir_out(gc, gpio, val); |
---|
415 | 415 | return 0; |
---|
416 | 416 | } |
---|
417 | 417 | |
---|
.. | .. |
---|
541 | 541 | void __iomem *dirin, |
---|
542 | 542 | unsigned long flags) |
---|
543 | 543 | { |
---|
544 | | - if (dirout && dirin) { |
---|
545 | | - return -EINVAL; |
---|
546 | | - } else if (dirout) { |
---|
547 | | - gc->reg_dir = dirout; |
---|
548 | | - gc->direction_output = bgpio_dir_out; |
---|
| 544 | + if (dirout || dirin) { |
---|
| 545 | + gc->reg_dir_out = dirout; |
---|
| 546 | + gc->reg_dir_in = dirin; |
---|
| 547 | + if (flags & BGPIOF_NO_SET_ON_INPUT) |
---|
| 548 | + gc->direction_output = bgpio_dir_out_dir_first; |
---|
| 549 | + else |
---|
| 550 | + gc->direction_output = bgpio_dir_out_val_first; |
---|
549 | 551 | gc->direction_input = bgpio_dir_in; |
---|
550 | 552 | gc->get_direction = bgpio_get_dir; |
---|
551 | | - } else if (dirin) { |
---|
552 | | - gc->reg_dir = dirin; |
---|
553 | | - gc->direction_output = bgpio_dir_out; |
---|
554 | | - gc->direction_input = bgpio_dir_in; |
---|
555 | | - gc->get_direction = bgpio_get_dir; |
---|
556 | | - gc->bgpio_dir_inverted = true; |
---|
557 | 553 | } else { |
---|
558 | 554 | if (flags & BGPIOF_NO_OUTPUT) |
---|
559 | 555 | gc->direction_output = bgpio_dir_out_err; |
---|
.. | .. |
---|
592 | 588 | * @dirout: MMIO address for the register to set the line as OUTPUT. It is assumed |
---|
593 | 589 | * that setting a line to 1 in this register will turn that line into an |
---|
594 | 590 | * output line. Conversely, setting the line to 0 will turn that line into |
---|
595 | | - * an input. Either this or @dirin can be defined, but never both. |
---|
| 591 | + * an input. |
---|
596 | 592 | * @dirin: MMIO address for the register to set this line as INPUT. It is assumed |
---|
597 | 593 | * that setting a line to 1 in this register will turn that line into an |
---|
598 | 594 | * input line. Conversely, setting the line to 0 will turn that line into |
---|
599 | | - * an output. Either this or @dirout can be defined, but never both. |
---|
| 595 | + * an output. |
---|
600 | 596 | * @flags: Different flags that will affect the behaviour of the device, such as |
---|
601 | 597 | * endianness etc. |
---|
602 | 598 | */ |
---|
.. | .. |
---|
638 | 634 | if (gc->set == bgpio_set_set && |
---|
639 | 635 | !(flags & BGPIOF_UNREADABLE_REG_SET)) |
---|
640 | 636 | gc->bgpio_data = gc->read_reg(gc->reg_set); |
---|
641 | | - if (gc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR)) |
---|
642 | | - gc->bgpio_dir = gc->read_reg(gc->reg_dir); |
---|
| 637 | + |
---|
| 638 | + if (flags & BGPIOF_UNREADABLE_REG_DIR) |
---|
| 639 | + gc->bgpio_dir_unreadable = true; |
---|
| 640 | + |
---|
| 641 | + /* |
---|
| 642 | + * Inspect hardware to find initial direction setting. |
---|
| 643 | + */ |
---|
| 644 | + if ((gc->reg_dir_out || gc->reg_dir_in) && |
---|
| 645 | + !(flags & BGPIOF_UNREADABLE_REG_DIR)) { |
---|
| 646 | + if (gc->reg_dir_out) |
---|
| 647 | + gc->bgpio_dir = gc->read_reg(gc->reg_dir_out); |
---|
| 648 | + else if (gc->reg_dir_in) |
---|
| 649 | + gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in); |
---|
| 650 | + /* |
---|
| 651 | + * If we have two direction registers, synchronise |
---|
| 652 | + * input setting to output setting, the library |
---|
| 653 | + * can not handle a line being input and output at |
---|
| 654 | + * the same time. |
---|
| 655 | + */ |
---|
| 656 | + if (gc->reg_dir_out && gc->reg_dir_in) |
---|
| 657 | + gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir); |
---|
| 658 | + } |
---|
643 | 659 | |
---|
644 | 660 | return ret; |
---|
645 | 661 | } |
---|