hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/gpio/gpio-ws16c48.c
....@@ -1,15 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * GPIO driver for the WinSystems WS16C48
34 * 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.
135 */
146 #include <linux/bitmap.h>
157 #include <linux/bitops.h>
....@@ -64,7 +56,10 @@
6456 const unsigned port = offset / 8;
6557 const unsigned mask = BIT(offset % 8);
6658
67
- return !!(ws16c48gpio->io_state[port] & mask);
59
+ if (ws16c48gpio->io_state[port] & mask)
60
+ return GPIO_LINE_DIRECTION_IN;
61
+
62
+ return GPIO_LINE_DIRECTION_OUT;
6863 }
6964
7065 static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
....@@ -134,42 +129,19 @@
134129 unsigned long *mask, unsigned long *bits)
135130 {
136131 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
137
- const unsigned int gpio_reg_size = 8;
138
- size_t i;
139
- const size_t num_ports = chip->ngpio / gpio_reg_size;
140
- unsigned int bits_offset;
141
- size_t word_index;
142
- unsigned int word_offset;
143
- unsigned long word_mask;
144
- const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
132
+ unsigned long offset;
133
+ unsigned long gpio_mask;
134
+ unsigned int port_addr;
145135 unsigned long port_state;
146136
147137 /* clear bits array to a clean slate */
148138 bitmap_zero(bits, chip->ngpio);
149139
150
- /* get bits are evaluated a gpio port register at a time */
151
- for (i = 0; i < num_ports; i++) {
152
- /* gpio offset in bits array */
153
- bits_offset = i * gpio_reg_size;
140
+ for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) {
141
+ port_addr = ws16c48gpio->base + offset / 8;
142
+ port_state = inb(port_addr) & gpio_mask;
154143
155
- /* word index for bits array */
156
- word_index = BIT_WORD(bits_offset);
157
-
158
- /* gpio offset within current word of bits array */
159
- word_offset = bits_offset % BITS_PER_LONG;
160
-
161
- /* mask of get bits for current gpio within current word */
162
- word_mask = mask[word_index] & (port_mask << word_offset);
163
- if (!word_mask) {
164
- /* no get bits in this port so skip to next one */
165
- continue;
166
- }
167
-
168
- /* read bits from current gpio port */
169
- port_state = inb(ws16c48gpio->base + i);
170
-
171
- /* store acquired bits at respective bits array offset */
172
- bits[word_index] |= port_state << word_offset;
144
+ bitmap_set_value8(bits, port_state, offset);
173145 }
174146
175147 return 0;
....@@ -203,39 +175,29 @@
203175 unsigned long *mask, unsigned long *bits)
204176 {
205177 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
206
- unsigned int i;
207
- const unsigned int gpio_reg_size = 8;
208
- unsigned int port;
209
- unsigned int iomask;
210
- unsigned int bitmask;
178
+ unsigned long offset;
179
+ unsigned long gpio_mask;
180
+ size_t index;
181
+ unsigned int port_addr;
182
+ unsigned long bitmask;
211183 unsigned long flags;
212184
213
- /* set bits are evaluated a gpio register size at a time */
214
- for (i = 0; i < chip->ngpio; i += gpio_reg_size) {
215
- /* no more set bits in this mask word; skip to the next word */
216
- if (!mask[BIT_WORD(i)]) {
217
- i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size;
218
- continue;
219
- }
220
-
221
- port = i / gpio_reg_size;
185
+ for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) {
186
+ index = offset / 8;
187
+ port_addr = ws16c48gpio->base + index;
222188
223189 /* mask out GPIO configured for input */
224
- iomask = mask[BIT_WORD(i)] & ~ws16c48gpio->io_state[port];
225
- bitmask = iomask & bits[BIT_WORD(i)];
190
+ gpio_mask &= ~ws16c48gpio->io_state[index];
191
+ bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
226192
227193 raw_spin_lock_irqsave(&ws16c48gpio->lock, flags);
228194
229195 /* update output state data and set device gpio register */
230
- ws16c48gpio->out_state[port] &= ~iomask;
231
- ws16c48gpio->out_state[port] |= bitmask;
232
- outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
196
+ ws16c48gpio->out_state[index] &= ~gpio_mask;
197
+ ws16c48gpio->out_state[index] |= bitmask;
198
+ outb(ws16c48gpio->out_state[index], port_addr);
233199
234200 raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags);
235
-
236
- /* prepare for next gpio register set */
237
- mask[BIT_WORD(i)] >>= gpio_reg_size;
238
- bits[BIT_WORD(i)] >>= gpio_reg_size;
239201 }
240202 }
241203
....@@ -403,10 +365,25 @@
403365 "Port 5 Bit 4", "Port 5 Bit 5", "Port 5 Bit 6", "Port 5 Bit 7"
404366 };
405367
368
+static int ws16c48_irq_init_hw(struct gpio_chip *gc)
369
+{
370
+ struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(gc);
371
+
372
+ /* Disable IRQ by default */
373
+ outb(0x80, ws16c48gpio->base + 7);
374
+ outb(0, ws16c48gpio->base + 8);
375
+ outb(0, ws16c48gpio->base + 9);
376
+ outb(0, ws16c48gpio->base + 10);
377
+ outb(0xC0, ws16c48gpio->base + 7);
378
+
379
+ return 0;
380
+}
381
+
406382 static int ws16c48_probe(struct device *dev, unsigned int id)
407383 {
408384 struct ws16c48_gpio *ws16c48gpio;
409385 const char *const name = dev_name(dev);
386
+ struct gpio_irq_chip *girq;
410387 int err;
411388
412389 ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL);
....@@ -434,25 +411,21 @@
434411 ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple;
435412 ws16c48gpio->base = base[id];
436413
414
+ girq = &ws16c48gpio->chip.irq;
415
+ girq->chip = &ws16c48_irqchip;
416
+ /* This will let us handle the parent IRQ in the driver */
417
+ girq->parent_handler = NULL;
418
+ girq->num_parents = 0;
419
+ girq->parents = NULL;
420
+ girq->default_type = IRQ_TYPE_NONE;
421
+ girq->handler = handle_edge_irq;
422
+ girq->init_hw = ws16c48_irq_init_hw;
423
+
437424 raw_spin_lock_init(&ws16c48gpio->lock);
438425
439426 err = devm_gpiochip_add_data(dev, &ws16c48gpio->chip, ws16c48gpio);
440427 if (err) {
441428 dev_err(dev, "GPIO registering failed (%d)\n", err);
442
- return err;
443
- }
444
-
445
- /* Disable IRQ by default */
446
- outb(0x80, base[id] + 7);
447
- outb(0, base[id] + 8);
448
- outb(0, base[id] + 9);
449
- outb(0, base[id] + 10);
450
- outb(0xC0, base[id] + 7);
451
-
452
- err = gpiochip_irqchip_add(&ws16c48gpio->chip, &ws16c48_irqchip, 0,
453
- handle_edge_irq, IRQ_TYPE_NONE);
454
- if (err) {
455
- dev_err(dev, "Could not add irqchip (%d)\n", err);
456429 return err;
457430 }
458431