6
6
* This driver supports the following ACCES devices: 104-IDI-48A,
7
7
* 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC.
8
8
*/
9
- #include <linux/bitmap.h>
10
- #include <linux/bitops.h>
9
+ #include <linux/bits.h>
11
10
#include <linux/device.h>
12
11
#include <linux/errno.h>
13
12
#include <linux/gpio/driver.h>
20
19
#include <linux/module.h>
21
20
#include <linux/moduleparam.h>
22
21
#include <linux/spinlock.h>
22
+ #include <linux/types.h>
23
+
24
+ #include "gpio-i8255.h"
25
+
26
+ MODULE_IMPORT_NS (I8255 );
23
27
24
28
#define IDI_48_EXTENT 8
25
29
#define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT)
@@ -33,21 +37,34 @@ static unsigned int irq[MAX_NUM_IDI_48];
33
37
module_param_hw_array (irq , uint , irq , NULL , 0 );
34
38
MODULE_PARM_DESC (irq , "ACCES 104-IDI-48 interrupt line numbers" );
35
39
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
+
36
55
/**
37
56
* struct idi_48_gpio - GPIO device private data structure
38
57
* @chip: instance of the gpio_chip
39
58
* @lock: synchronization lock to prevent I/O race conditions
40
- * @ack_lock: synchronization lock to prevent IRQ handler race conditions
41
59
* @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
43
61
* @cos_enb: Change-Of-State IRQ enable boundaries mask
44
62
*/
45
63
struct idi_48_gpio {
46
64
struct gpio_chip chip ;
47
- raw_spinlock_t lock ;
48
- spinlock_t ack_lock ;
65
+ spinlock_t lock ;
49
66
unsigned char irq_mask [6 ];
50
- void __iomem * base ;
67
+ struct idi_48_reg __iomem * reg ;
51
68
unsigned char cos_enb ;
52
69
};
53
70
@@ -64,42 +81,18 @@ static int idi_48_gpio_direction_input(struct gpio_chip *chip, unsigned int offs
64
81
static int idi_48_gpio_get (struct gpio_chip * chip , unsigned int offset )
65
82
{
66
83
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 ;
79
85
80
- /* The following line should never execute since offset < 48 */
81
- return 0 ;
86
+ return i8255_get (ppi , offset );
82
87
}
83
88
84
89
static int idi_48_gpio_get_multiple (struct gpio_chip * chip , unsigned long * mask ,
85
90
unsigned long * bits )
86
91
{
87
92
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 ;
96
94
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 );
103
96
104
97
return 0 ;
105
98
}
@@ -113,63 +106,52 @@ static void idi_48_irq_mask(struct irq_data *data)
113
106
struct gpio_chip * chip = irq_data_get_irq_chip_data (data );
114
107
struct idi_48_gpio * const idi48gpio = gpiochip_get_data (chip );
115
108
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 );
119
111
unsigned long flags ;
120
112
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 );
127
114
128
- if (!idi48gpio -> irq_mask [boundary ]) {
129
- idi48gpio -> cos_enb &= ~BIT (boundary );
115
+ idi48gpio -> irq_mask [boundary ] &= ~mask ;
130
116
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 ;
132
120
133
- iowrite8 ( idi48gpio -> cos_enb , idi48gpio -> base + 7 );
121
+ idi48gpio -> cos_enb &= ~ BIT ( boundary );
134
122
135
- raw_spin_unlock_irqrestore (& idi48gpio -> lock , flags );
136
- }
123
+ iowrite8 (idi48gpio -> cos_enb , & idi48gpio -> reg -> irq );
137
124
138
- return ;
139
- }
125
+ exit :
126
+ spin_unlock_irqrestore ( & idi48gpio -> lock , flags );
140
127
}
141
128
142
129
static void idi_48_irq_unmask (struct irq_data * data )
143
130
{
144
131
struct gpio_chip * chip = irq_data_get_irq_chip_data (data );
145
132
struct idi_48_gpio * const idi48gpio = gpiochip_get_data (chip );
146
133
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 );
150
136
unsigned int prev_irq_mask ;
151
137
unsigned long flags ;
152
138
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 );
158
140
159
- idi48gpio -> irq_mask [boundary ] |= mask ;
141
+ prev_irq_mask = idi48gpio -> irq_mask [boundary ];
160
142
161
- if (!prev_irq_mask ) {
162
- idi48gpio -> cos_enb |= BIT (boundary );
143
+ idi48gpio -> irq_mask [boundary ] |= mask ;
163
144
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 ;
165
148
166
- iowrite8 ( idi48gpio -> cos_enb , idi48gpio -> base + 7 );
149
+ idi48gpio -> cos_enb |= BIT ( boundary );
167
150
168
- raw_spin_unlock_irqrestore (& idi48gpio -> lock , flags );
169
- }
151
+ iowrite8 (idi48gpio -> cos_enb , & idi48gpio -> reg -> irq );
170
152
171
- return ;
172
- }
153
+ exit :
154
+ spin_unlock_irqrestore ( & idi48gpio -> lock , flags );
173
155
}
174
156
175
157
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)
200
182
unsigned long gpio ;
201
183
struct gpio_chip * const chip = & idi48gpio -> chip ;
202
184
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 );
208
186
209
- raw_spin_unlock (& idi48gpio -> lock );
187
+ cos_status = ioread8 (& idi48gpio -> reg -> irq );
210
188
211
189
/* IRQ Status (bit 6) is active low (0 = IRQ generated by device) */
212
190
if (cos_status & BIT (6 )) {
213
- spin_unlock (& idi48gpio -> ack_lock );
191
+ spin_unlock (& idi48gpio -> lock );
214
192
return IRQ_NONE ;
215
193
}
216
194
@@ -228,7 +206,7 @@ static irqreturn_t idi_48_irq_handler(int irq, void *dev_id)
228
206
}
229
207
}
230
208
231
- spin_unlock (& idi48gpio -> ack_lock );
209
+ spin_unlock (& idi48gpio -> lock );
232
210
233
211
return IRQ_HANDLED ;
234
212
}
@@ -250,8 +228,8 @@ static int idi_48_irq_init_hw(struct gpio_chip *gc)
250
228
struct idi_48_gpio * const idi48gpio = gpiochip_get_data (gc );
251
229
252
230
/* 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 );
255
233
256
234
return 0 ;
257
235
}
@@ -273,8 +251,8 @@ static int idi_48_probe(struct device *dev, unsigned int id)
273
251
return - EBUSY ;
274
252
}
275
253
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 )
278
256
return - ENOMEM ;
279
257
280
258
idi48gpio -> chip .label = name ;
@@ -298,8 +276,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
298
276
girq -> handler = handle_edge_irq ;
299
277
girq -> init_hw = idi_48_irq_init_hw ;
300
278
301
- raw_spin_lock_init (& idi48gpio -> lock );
302
- spin_lock_init (& idi48gpio -> ack_lock );
279
+ spin_lock_init (& idi48gpio -> lock );
303
280
304
281
err = devm_gpiochip_add_data (dev , & idi48gpio -> chip , idi48gpio );
305
282
if (err ) {
0 commit comments