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>
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];
3337module_param_hw_array (irq , uint , irq , NULL , 0 );
3438MODULE_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 */
4563struct 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
6481static 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
8489static 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
142129static 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
175157static 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