|
11 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12 | 12 | * General Public License for more details.
|
13 | 13 | */
|
| 14 | +#include <linux/bitmap.h> |
14 | 15 | #include <linux/bitops.h>
|
15 | 16 | #include <linux/device.h>
|
16 | 17 | #include <linux/errno.h>
|
@@ -103,6 +104,54 @@ static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
103 | 104 | return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24));
|
104 | 105 | }
|
105 | 106 |
|
| 107 | +static int idio_16_gpio_get_multiple(struct gpio_chip *chip, |
| 108 | + unsigned long *mask, unsigned long *bits) |
| 109 | +{ |
| 110 | + struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); |
| 111 | + size_t i; |
| 112 | + const unsigned int gpio_reg_size = 8; |
| 113 | + unsigned int bits_offset; |
| 114 | + size_t word_index; |
| 115 | + unsigned int word_offset; |
| 116 | + unsigned long word_mask; |
| 117 | + const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); |
| 118 | + unsigned long port_state; |
| 119 | + u8 __iomem ports[] = { |
| 120 | + idio16gpio->reg->out0_7, idio16gpio->reg->out8_15, |
| 121 | + idio16gpio->reg->in0_7, idio16gpio->reg->in8_15, |
| 122 | + }; |
| 123 | + |
| 124 | + /* clear bits array to a clean slate */ |
| 125 | + bitmap_zero(bits, chip->ngpio); |
| 126 | + |
| 127 | + /* get bits are evaluated a gpio port register at a time */ |
| 128 | + for (i = 0; i < ARRAY_SIZE(ports); i++) { |
| 129 | + /* gpio offset in bits array */ |
| 130 | + bits_offset = i * gpio_reg_size; |
| 131 | + |
| 132 | + /* word index for bits array */ |
| 133 | + word_index = BIT_WORD(bits_offset); |
| 134 | + |
| 135 | + /* gpio offset within current word of bits array */ |
| 136 | + word_offset = bits_offset % BITS_PER_LONG; |
| 137 | + |
| 138 | + /* mask of get bits for current gpio within current word */ |
| 139 | + word_mask = mask[word_index] & (port_mask << word_offset); |
| 140 | + if (!word_mask) { |
| 141 | + /* no get bits in this port so skip to next one */ |
| 142 | + continue; |
| 143 | + } |
| 144 | + |
| 145 | + /* read bits from current gpio port */ |
| 146 | + port_state = ioread8(ports + i); |
| 147 | + |
| 148 | + /* store acquired bits at respective bits array offset */ |
| 149 | + bits[word_index] |= port_state << word_offset; |
| 150 | + } |
| 151 | + |
| 152 | + return 0; |
| 153 | +} |
| 154 | + |
106 | 155 | static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
107 | 156 | int value)
|
108 | 157 | {
|
@@ -299,6 +348,7 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
299 | 348 | idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
|
300 | 349 | idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
|
301 | 350 | idio16gpio->chip.get = idio_16_gpio_get;
|
| 351 | + idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple; |
302 | 352 | idio16gpio->chip.set = idio_16_gpio_set;
|
303 | 353 | idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
|
304 | 354 |
|
|
0 commit comments