.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * GPIO driver for the Diamond Systems GPIO-MM |
---|
3 | 4 | * Copyright (C) 2016 William Breathitt Gray |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify |
---|
6 | | - * it under the terms of the GNU General Public License, version 2, as |
---|
7 | | - * published by the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope that it will be useful, but |
---|
10 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
12 | | - * General Public License for more details. |
---|
13 | 5 | * |
---|
14 | 6 | * This driver supports the following Diamond Systems devices: GPIO-MM and |
---|
15 | 7 | * GPIO-MM-12. |
---|
.. | .. |
---|
60 | 52 | const unsigned int port = offset / 8; |
---|
61 | 53 | const unsigned int mask = BIT(offset % 8); |
---|
62 | 54 | |
---|
63 | | - return !!(gpiommgpio->io_state[port] & mask); |
---|
| 55 | + if (gpiommgpio->io_state[port] & mask) |
---|
| 56 | + return GPIO_LINE_DIRECTION_IN; |
---|
| 57 | + |
---|
| 58 | + return GPIO_LINE_DIRECTION_OUT; |
---|
64 | 59 | } |
---|
65 | 60 | |
---|
66 | 61 | static int gpiomm_gpio_direction_input(struct gpio_chip *chip, |
---|
.. | .. |
---|
172 | 167 | return !!(port_state & mask); |
---|
173 | 168 | } |
---|
174 | 169 | |
---|
| 170 | +static const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; |
---|
| 171 | + |
---|
175 | 172 | static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, |
---|
176 | 173 | unsigned long *bits) |
---|
177 | 174 | { |
---|
178 | 175 | struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); |
---|
179 | | - size_t i; |
---|
180 | | - static const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; |
---|
181 | | - const unsigned int gpio_reg_size = 8; |
---|
182 | | - unsigned int bits_offset; |
---|
183 | | - size_t word_index; |
---|
184 | | - unsigned int word_offset; |
---|
185 | | - unsigned long word_mask; |
---|
186 | | - const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0); |
---|
| 176 | + unsigned long offset; |
---|
| 177 | + unsigned long gpio_mask; |
---|
| 178 | + unsigned int port_addr; |
---|
187 | 179 | unsigned long port_state; |
---|
188 | 180 | |
---|
189 | 181 | /* clear bits array to a clean slate */ |
---|
190 | 182 | bitmap_zero(bits, chip->ngpio); |
---|
191 | 183 | |
---|
192 | | - /* get bits are evaluated a gpio port register at a time */ |
---|
193 | | - for (i = 0; i < ARRAY_SIZE(ports); i++) { |
---|
194 | | - /* gpio offset in bits array */ |
---|
195 | | - bits_offset = i * gpio_reg_size; |
---|
| 184 | + for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { |
---|
| 185 | + port_addr = gpiommgpio->base + ports[offset / 8]; |
---|
| 186 | + port_state = inb(port_addr) & gpio_mask; |
---|
196 | 187 | |
---|
197 | | - /* word index for bits array */ |
---|
198 | | - word_index = BIT_WORD(bits_offset); |
---|
199 | | - |
---|
200 | | - /* gpio offset within current word of bits array */ |
---|
201 | | - word_offset = bits_offset % BITS_PER_LONG; |
---|
202 | | - |
---|
203 | | - /* mask of get bits for current gpio within current word */ |
---|
204 | | - word_mask = mask[word_index] & (port_mask << word_offset); |
---|
205 | | - if (!word_mask) { |
---|
206 | | - /* no get bits in this port so skip to next one */ |
---|
207 | | - continue; |
---|
208 | | - } |
---|
209 | | - |
---|
210 | | - /* read bits from current gpio port */ |
---|
211 | | - port_state = inb(gpiommgpio->base + ports[i]); |
---|
212 | | - |
---|
213 | | - /* store acquired bits at respective bits array offset */ |
---|
214 | | - bits[word_index] |= port_state << word_offset; |
---|
| 188 | + bitmap_set_value8(bits, port_state, offset); |
---|
215 | 189 | } |
---|
216 | 190 | |
---|
217 | 191 | return 0; |
---|
.. | .. |
---|
242 | 216 | unsigned long *mask, unsigned long *bits) |
---|
243 | 217 | { |
---|
244 | 218 | struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); |
---|
245 | | - unsigned int i; |
---|
246 | | - const unsigned int gpio_reg_size = 8; |
---|
247 | | - unsigned int port; |
---|
248 | | - unsigned int out_port; |
---|
249 | | - unsigned int bitmask; |
---|
| 219 | + unsigned long offset; |
---|
| 220 | + unsigned long gpio_mask; |
---|
| 221 | + size_t index; |
---|
| 222 | + unsigned int port_addr; |
---|
| 223 | + unsigned long bitmask; |
---|
250 | 224 | unsigned long flags; |
---|
251 | 225 | |
---|
252 | | - /* set bits are evaluated a gpio register size at a time */ |
---|
253 | | - for (i = 0; i < chip->ngpio; i += gpio_reg_size) { |
---|
254 | | - /* no more set bits in this mask word; skip to the next word */ |
---|
255 | | - if (!mask[BIT_WORD(i)]) { |
---|
256 | | - i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size; |
---|
257 | | - continue; |
---|
258 | | - } |
---|
| 226 | + for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { |
---|
| 227 | + index = offset / 8; |
---|
| 228 | + port_addr = gpiommgpio->base + ports[index]; |
---|
259 | 229 | |
---|
260 | | - port = i / gpio_reg_size; |
---|
261 | | - out_port = (port > 2) ? port + 1 : port; |
---|
262 | | - bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)]; |
---|
| 230 | + bitmask = bitmap_get_value8(bits, offset) & gpio_mask; |
---|
263 | 231 | |
---|
264 | 232 | spin_lock_irqsave(&gpiommgpio->lock, flags); |
---|
265 | 233 | |
---|
266 | 234 | /* update output state data and set device gpio register */ |
---|
267 | | - gpiommgpio->out_state[port] &= ~mask[BIT_WORD(i)]; |
---|
268 | | - gpiommgpio->out_state[port] |= bitmask; |
---|
269 | | - outb(gpiommgpio->out_state[port], gpiommgpio->base + out_port); |
---|
| 235 | + gpiommgpio->out_state[index] &= ~gpio_mask; |
---|
| 236 | + gpiommgpio->out_state[index] |= bitmask; |
---|
| 237 | + outb(gpiommgpio->out_state[index], port_addr); |
---|
270 | 238 | |
---|
271 | 239 | spin_unlock_irqrestore(&gpiommgpio->lock, flags); |
---|
272 | | - |
---|
273 | | - /* prepare for next gpio register set */ |
---|
274 | | - mask[BIT_WORD(i)] >>= gpio_reg_size; |
---|
275 | | - bits[BIT_WORD(i)] >>= gpio_reg_size; |
---|
276 | 240 | } |
---|
277 | 241 | } |
---|
278 | 242 | |
---|