Skip to content

Commit 3ce632f

Browse files
William Breathitt Graybrgl
authored andcommitted
gpio: 104-idi-48: Implement and utilize register structures
Reduce magic numbers and improve code readability by implementing and utilizing named register data structures. The 104-IDI-48 device features an Intel 8255 compatible GPIO interface, so the i8255 GPIO module is selected and utilized as well. Reviewed-by: Linus Walleij <[email protected]> Cc: John Hentges <[email protected]> Cc: Jay Dolan <[email protected]> Signed-off-by: William Breathitt Gray <[email protected]> Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent 71b7b39 commit 3ce632f

File tree

2 files changed

+61
-83
lines changed

2 files changed

+61
-83
lines changed

drivers/gpio/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@ config GPIO_104_IDI_48
865865
depends on PC104
866866
select ISA_BUS_API
867867
select GPIOLIB_IRQCHIP
868+
select GPIO_I8255
868869
help
869870
Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
870871
104-IDI-48AC, 104-IDI-48B, 104-IDI-48BC). The base port addresses for

drivers/gpio/gpio-104-idi-48.c

Lines changed: 60 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
* This driver supports the following ACCES devices: 104-IDI-48A,
77
* 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC.
88
*/
9-
#include <linux/bitmap.h>
10-
#include <linux/bitops.h>
9+
#include <linux/bits.h>
1110
#include <linux/device.h>
1211
#include <linux/errno.h>
1312
#include <linux/gpio/driver.h>
@@ -20,6 +19,11 @@
2019
#include <linux/module.h>
2120
#include <linux/moduleparam.h>
2221
#include <linux/spinlock.h>
22+
#include <linux/types.h>
23+
24+
#include "gpio-i8255.h"
25+
26+
MODULE_IMPORT_NS(I8255);
2327

2428
#define IDI_48_EXTENT 8
2529
#define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT)
@@ -33,21 +37,34 @@ static unsigned int irq[MAX_NUM_IDI_48];
3337
module_param_hw_array(irq, uint, irq, NULL, 0);
3438
MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
3539

40+
/**
41+
* struct idi_48_reg - device register structure
42+
* @port0: Port 0 Inputs
43+
* @unused: Unused
44+
* @port1: Port 1 Inputs
45+
* @irq: Read: IRQ Status Register/IRQ Clear
46+
* Write: IRQ Enable/Disable
47+
*/
48+
struct idi_48_reg {
49+
u8 port0[3];
50+
u8 unused;
51+
u8 port1[3];
52+
u8 irq;
53+
};
54+
3655
/**
3756
* struct idi_48_gpio - GPIO device private data structure
3857
* @chip: instance of the gpio_chip
3958
* @lock: synchronization lock to prevent I/O race conditions
40-
* @ack_lock: synchronization lock to prevent IRQ handler race conditions
4159
* @irq_mask: input bits affected by interrupts
42-
* @base: base port address of the GPIO device
60+
* @reg: I/O address offset for the device registers
4361
* @cos_enb: Change-Of-State IRQ enable boundaries mask
4462
*/
4563
struct idi_48_gpio {
4664
struct gpio_chip chip;
47-
raw_spinlock_t lock;
48-
spinlock_t ack_lock;
65+
spinlock_t lock;
4966
unsigned char irq_mask[6];
50-
void __iomem *base;
67+
struct idi_48_reg __iomem *reg;
5168
unsigned char cos_enb;
5269
};
5370

@@ -64,42 +81,18 @@ static int idi_48_gpio_direction_input(struct gpio_chip *chip, unsigned int offs
6481
static int idi_48_gpio_get(struct gpio_chip *chip, unsigned int offset)
6582
{
6683
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
67-
unsigned int i;
68-
static const unsigned int register_offset[6] = { 0, 1, 2, 4, 5, 6 };
69-
void __iomem *port_addr;
70-
unsigned int mask;
71-
72-
for (i = 0; i < 48; i += 8)
73-
if (offset < i + 8) {
74-
port_addr = idi48gpio->base + register_offset[i / 8];
75-
mask = BIT(offset - i);
76-
77-
return !!(ioread8(port_addr) & mask);
78-
}
84+
void __iomem *const ppi = idi48gpio->reg;
7985

80-
/* The following line should never execute since offset < 48 */
81-
return 0;
86+
return i8255_get(ppi, offset);
8287
}
8388

8489
static int idi_48_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
8590
unsigned long *bits)
8691
{
8792
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
88-
unsigned long offset;
89-
unsigned long gpio_mask;
90-
static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
91-
void __iomem *port_addr;
92-
unsigned long port_state;
93-
94-
/* clear bits array to a clean slate */
95-
bitmap_zero(bits, chip->ngpio);
93+
void __iomem *const ppi = idi48gpio->reg;
9694

97-
for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
98-
port_addr = idi48gpio->base + ports[offset / 8];
99-
port_state = ioread8(port_addr) & gpio_mask;
100-
101-
bitmap_set_value8(bits, port_state, offset);
102-
}
95+
i8255_get_multiple(ppi, mask, bits, chip->ngpio);
10396

10497
return 0;
10598
}
@@ -113,63 +106,52 @@ static void idi_48_irq_mask(struct irq_data *data)
113106
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
114107
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
115108
const unsigned int offset = irqd_to_hwirq(data);
116-
unsigned int i;
117-
unsigned int mask;
118-
unsigned int boundary;
109+
const unsigned long boundary = offset / 8;
110+
const unsigned long mask = BIT(offset % 8);
119111
unsigned long flags;
120112

121-
for (i = 0; i < 48; i += 8)
122-
if (offset < i + 8) {
123-
mask = BIT(offset - i);
124-
boundary = i / 8;
125-
126-
idi48gpio->irq_mask[boundary] &= ~mask;
113+
spin_lock_irqsave(&idi48gpio->lock, flags);
127114

128-
if (!idi48gpio->irq_mask[boundary]) {
129-
idi48gpio->cos_enb &= ~BIT(boundary);
115+
idi48gpio->irq_mask[boundary] &= ~mask;
130116

131-
raw_spin_lock_irqsave(&idi48gpio->lock, flags);
117+
/* Exit early if there are still input lines with IRQ unmasked */
118+
if (idi48gpio->irq_mask[boundary])
119+
goto exit;
132120

133-
iowrite8(idi48gpio->cos_enb, idi48gpio->base + 7);
121+
idi48gpio->cos_enb &= ~BIT(boundary);
134122

135-
raw_spin_unlock_irqrestore(&idi48gpio->lock, flags);
136-
}
123+
iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq);
137124

138-
return;
139-
}
125+
exit:
126+
spin_unlock_irqrestore(&idi48gpio->lock, flags);
140127
}
141128

142129
static void idi_48_irq_unmask(struct irq_data *data)
143130
{
144131
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
145132
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
146133
const unsigned int offset = irqd_to_hwirq(data);
147-
unsigned int i;
148-
unsigned int mask;
149-
unsigned int boundary;
134+
const unsigned long boundary = offset / 8;
135+
const unsigned long mask = BIT(offset % 8);
150136
unsigned int prev_irq_mask;
151137
unsigned long flags;
152138

153-
for (i = 0; i < 48; i += 8)
154-
if (offset < i + 8) {
155-
mask = BIT(offset - i);
156-
boundary = i / 8;
157-
prev_irq_mask = idi48gpio->irq_mask[boundary];
139+
spin_lock_irqsave(&idi48gpio->lock, flags);
158140

159-
idi48gpio->irq_mask[boundary] |= mask;
141+
prev_irq_mask = idi48gpio->irq_mask[boundary];
160142

161-
if (!prev_irq_mask) {
162-
idi48gpio->cos_enb |= BIT(boundary);
143+
idi48gpio->irq_mask[boundary] |= mask;
163144

164-
raw_spin_lock_irqsave(&idi48gpio->lock, flags);
145+
/* Exit early if IRQ was already unmasked for this boundary */
146+
if (prev_irq_mask)
147+
goto exit;
165148

166-
iowrite8(idi48gpio->cos_enb, idi48gpio->base + 7);
149+
idi48gpio->cos_enb |= BIT(boundary);
167150

168-
raw_spin_unlock_irqrestore(&idi48gpio->lock, flags);
169-
}
151+
iowrite8(idi48gpio->cos_enb, &idi48gpio->reg->irq);
170152

171-
return;
172-
}
153+
exit:
154+
spin_unlock_irqrestore(&idi48gpio->lock, flags);
173155
}
174156

175157
static int idi_48_irq_set_type(struct irq_data *data, unsigned int flow_type)
@@ -200,17 +182,13 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
200182
unsigned long gpio;
201183
struct gpio_chip *const chip = &idi48gpio->chip;
202184

203-
spin_lock(&idi48gpio->ack_lock);
204-
205-
raw_spin_lock(&idi48gpio->lock);
206-
207-
cos_status = ioread8(idi48gpio->base + 7);
185+
spin_lock(&idi48gpio->lock);
208186

209-
raw_spin_unlock(&idi48gpio->lock);
187+
cos_status = ioread8(&idi48gpio->reg->irq);
210188

211189
/* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
212190
if (cos_status & BIT(6)) {
213-
spin_unlock(&idi48gpio->ack_lock);
191+
spin_unlock(&idi48gpio->lock);
214192
return IRQ_NONE;
215193
}
216194

@@ -228,7 +206,7 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
228206
}
229207
}
230208

231-
spin_unlock(&idi48gpio->ack_lock);
209+
spin_unlock(&idi48gpio->lock);
232210

233211
return IRQ_HANDLED;
234212
}
@@ -250,8 +228,8 @@ static int idi_48_irq_init_hw(struct gpio_chip *gc)
250228
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(gc);
251229

252230
/* Disable IRQ by default */
253-
iowrite8(0, idi48gpio->base + 7);
254-
ioread8(idi48gpio->base + 7);
231+
iowrite8(0, &idi48gpio->reg->irq);
232+
ioread8(&idi48gpio->reg->irq);
255233

256234
return 0;
257235
}
@@ -273,8 +251,8 @@ static int idi_48_probe(struct device *dev, unsigned int id)
273251
return -EBUSY;
274252
}
275253

276-
idi48gpio->base = devm_ioport_map(dev, base[id], IDI_48_EXTENT);
277-
if (!idi48gpio->base)
254+
idi48gpio->reg = devm_ioport_map(dev, base[id], IDI_48_EXTENT);
255+
if (!idi48gpio->reg)
278256
return -ENOMEM;
279257

280258
idi48gpio->chip.label = name;
@@ -298,8 +276,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
298276
girq->handler = handle_edge_irq;
299277
girq->init_hw = idi_48_irq_init_hw;
300278

301-
raw_spin_lock_init(&idi48gpio->lock);
302-
spin_lock_init(&idi48gpio->ack_lock);
279+
spin_lock_init(&idi48gpio->lock);
303280

304281
err = devm_gpiochip_add_data(dev, &idi48gpio->chip, idi48gpio);
305282
if (err) {

0 commit comments

Comments
 (0)