2 * GPIO driver for the WinSystems WS16C48
3 * Copyright (C) 2016 William Breathitt Gray
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.
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.
14 #include <linux/bitops.h>
15 #include <linux/device.h>
16 #include <linux/errno.h>
17 #include <linux/gpio/driver.h>
19 #include <linux/ioport.h>
20 #include <linux/interrupt.h>
21 #include <linux/irqdesc.h>
22 #include <linux/isa.h>
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/moduleparam.h>
26 #include <linux/spinlock.h>
28 #define WS16C48_EXTENT 16
29 #define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT)
31 static unsigned int base
[MAX_NUM_WS16C48
];
32 static unsigned int num_ws16c48
;
33 module_param_array(base
, uint
, &num_ws16c48
, 0);
34 MODULE_PARM_DESC(base
, "WinSystems WS16C48 base addresses");
36 static unsigned int irq
[MAX_NUM_WS16C48
];
37 module_param_array(irq
, uint
, NULL
, 0);
38 MODULE_PARM_DESC(irq
, "WinSystems WS16C48 interrupt line numbers");
41 * struct ws16c48_gpio - GPIO device private data structure
42 * @chip: instance of the gpio_chip
43 * @io_state: bit I/O state (whether bit is set to input or output)
44 * @out_state: output bits state
45 * @lock: synchronization lock to prevent I/O race conditions
46 * @irq_mask: I/O bits affected by interrupts
47 * @flow_mask: IRQ flow type mask for the respective I/O bits
48 * @base: base port address of the GPIO device
49 * @irq: Interrupt line number
52 struct gpio_chip chip
;
53 unsigned char io_state
[6];
54 unsigned char out_state
[6];
56 unsigned long irq_mask
;
57 unsigned long flow_mask
;
62 static int ws16c48_gpio_get_direction(struct gpio_chip
*chip
, unsigned offset
)
64 struct ws16c48_gpio
*const ws16c48gpio
= gpiochip_get_data(chip
);
65 const unsigned port
= offset
/ 8;
66 const unsigned mask
= BIT(offset
% 8);
68 return !!(ws16c48gpio
->io_state
[port
] & mask
);
71 static int ws16c48_gpio_direction_input(struct gpio_chip
*chip
, unsigned offset
)
73 struct ws16c48_gpio
*const ws16c48gpio
= gpiochip_get_data(chip
);
74 const unsigned port
= offset
/ 8;
75 const unsigned mask
= BIT(offset
% 8);
78 spin_lock_irqsave(&ws16c48gpio
->lock
, flags
);
80 ws16c48gpio
->io_state
[port
] |= mask
;
81 ws16c48gpio
->out_state
[port
] &= ~mask
;
82 outb(ws16c48gpio
->out_state
[port
], ws16c48gpio
->base
+ port
);
84 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
89 static int ws16c48_gpio_direction_output(struct gpio_chip
*chip
,
90 unsigned offset
, int value
)
92 struct ws16c48_gpio
*const ws16c48gpio
= gpiochip_get_data(chip
);
93 const unsigned port
= offset
/ 8;
94 const unsigned mask
= BIT(offset
% 8);
97 spin_lock_irqsave(&ws16c48gpio
->lock
, flags
);
99 ws16c48gpio
->io_state
[port
] &= ~mask
;
101 ws16c48gpio
->out_state
[port
] |= mask
;
103 ws16c48gpio
->out_state
[port
] &= ~mask
;
104 outb(ws16c48gpio
->out_state
[port
], ws16c48gpio
->base
+ port
);
106 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
111 static int ws16c48_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
113 struct ws16c48_gpio
*const ws16c48gpio
= gpiochip_get_data(chip
);
114 const unsigned port
= offset
/ 8;
115 const unsigned mask
= BIT(offset
% 8);
119 spin_lock_irqsave(&ws16c48gpio
->lock
, flags
);
121 /* ensure that GPIO is set for input */
122 if (!(ws16c48gpio
->io_state
[port
] & mask
)) {
123 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
127 port_state
= inb(ws16c48gpio
->base
+ port
);
129 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
131 return !!(port_state
& mask
);
134 static void ws16c48_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
136 struct ws16c48_gpio
*const ws16c48gpio
= gpiochip_get_data(chip
);
137 const unsigned port
= offset
/ 8;
138 const unsigned mask
= BIT(offset
% 8);
141 spin_lock_irqsave(&ws16c48gpio
->lock
, flags
);
143 /* ensure that GPIO is set for output */
144 if (ws16c48gpio
->io_state
[port
] & mask
) {
145 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
150 ws16c48gpio
->out_state
[port
] |= mask
;
152 ws16c48gpio
->out_state
[port
] &= ~mask
;
153 outb(ws16c48gpio
->out_state
[port
], ws16c48gpio
->base
+ port
);
155 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
158 static void ws16c48_irq_ack(struct irq_data
*data
)
160 struct gpio_chip
*chip
= irq_data_get_irq_chip_data(data
);
161 struct ws16c48_gpio
*const ws16c48gpio
= gpiochip_get_data(chip
);
162 const unsigned long offset
= irqd_to_hwirq(data
);
163 const unsigned port
= offset
/ 8;
164 const unsigned mask
= BIT(offset
% 8);
168 /* only the first 3 ports support interrupts */
172 spin_lock_irqsave(&ws16c48gpio
->lock
, flags
);
174 port_state
= ws16c48gpio
->irq_mask
>> (8*port
);
176 outb(0x80, ws16c48gpio
->base
+ 7);
177 outb(port_state
& ~mask
, ws16c48gpio
->base
+ 8 + port
);
178 outb(port_state
| mask
, ws16c48gpio
->base
+ 8 + port
);
179 outb(0xC0, ws16c48gpio
->base
+ 7);
181 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
184 static void ws16c48_irq_mask(struct irq_data
*data
)
186 struct gpio_chip
*chip
= irq_data_get_irq_chip_data(data
);
187 struct ws16c48_gpio
*const ws16c48gpio
= gpiochip_get_data(chip
);
188 const unsigned long offset
= irqd_to_hwirq(data
);
189 const unsigned long mask
= BIT(offset
);
190 const unsigned port
= offset
/ 8;
193 /* only the first 3 ports support interrupts */
197 spin_lock_irqsave(&ws16c48gpio
->lock
, flags
);
199 ws16c48gpio
->irq_mask
&= ~mask
;
201 outb(0x80, ws16c48gpio
->base
+ 7);
202 outb(ws16c48gpio
->irq_mask
>> (8*port
), ws16c48gpio
->base
+ 8 + port
);
203 outb(0xC0, ws16c48gpio
->base
+ 7);
205 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
208 static void ws16c48_irq_unmask(struct irq_data
*data
)
210 struct gpio_chip
*chip
= irq_data_get_irq_chip_data(data
);
211 struct ws16c48_gpio
*const ws16c48gpio
= gpiochip_get_data(chip
);
212 const unsigned long offset
= irqd_to_hwirq(data
);
213 const unsigned long mask
= BIT(offset
);
214 const unsigned port
= offset
/ 8;
217 /* only the first 3 ports support interrupts */
221 spin_lock_irqsave(&ws16c48gpio
->lock
, flags
);
223 ws16c48gpio
->irq_mask
|= mask
;
225 outb(0x80, ws16c48gpio
->base
+ 7);
226 outb(ws16c48gpio
->irq_mask
>> (8*port
), ws16c48gpio
->base
+ 8 + port
);
227 outb(0xC0, ws16c48gpio
->base
+ 7);
229 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
232 static int ws16c48_irq_set_type(struct irq_data
*data
, unsigned flow_type
)
234 struct gpio_chip
*chip
= irq_data_get_irq_chip_data(data
);
235 struct ws16c48_gpio
*const ws16c48gpio
= gpiochip_get_data(chip
);
236 const unsigned long offset
= irqd_to_hwirq(data
);
237 const unsigned long mask
= BIT(offset
);
238 const unsigned port
= offset
/ 8;
241 /* only the first 3 ports support interrupts */
245 spin_lock_irqsave(&ws16c48gpio
->lock
, flags
);
250 case IRQ_TYPE_EDGE_RISING
:
251 ws16c48gpio
->flow_mask
|= mask
;
253 case IRQ_TYPE_EDGE_FALLING
:
254 ws16c48gpio
->flow_mask
&= ~mask
;
257 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
261 outb(0x40, ws16c48gpio
->base
+ 7);
262 outb(ws16c48gpio
->flow_mask
>> (8*port
), ws16c48gpio
->base
+ 8 + port
);
263 outb(0xC0, ws16c48gpio
->base
+ 7);
265 spin_unlock_irqrestore(&ws16c48gpio
->lock
, flags
);
270 static struct irq_chip ws16c48_irqchip
= {
272 .irq_ack
= ws16c48_irq_ack
,
273 .irq_mask
= ws16c48_irq_mask
,
274 .irq_unmask
= ws16c48_irq_unmask
,
275 .irq_set_type
= ws16c48_irq_set_type
278 static irqreturn_t
ws16c48_irq_handler(int irq
, void *dev_id
)
280 struct ws16c48_gpio
*const ws16c48gpio
= dev_id
;
281 struct gpio_chip
*const chip
= &ws16c48gpio
->chip
;
282 unsigned long int_pending
;
284 unsigned long int_id
;
287 int_pending
= inb(ws16c48gpio
->base
+ 6) & 0x7;
291 /* loop until all pending interrupts are handled */
293 for_each_set_bit(port
, &int_pending
, 3) {
294 int_id
= inb(ws16c48gpio
->base
+ 8 + port
);
295 for_each_set_bit(gpio
, &int_id
, 8)
296 generic_handle_irq(irq_find_mapping(
297 chip
->irqdomain
, gpio
+ 8*port
));
300 int_pending
= inb(ws16c48gpio
->base
+ 6) & 0x7;
301 } while (int_pending
);
306 static int ws16c48_probe(struct device
*dev
, unsigned int id
)
308 struct ws16c48_gpio
*ws16c48gpio
;
309 const char *const name
= dev_name(dev
);
312 ws16c48gpio
= devm_kzalloc(dev
, sizeof(*ws16c48gpio
), GFP_KERNEL
);
316 if (!devm_request_region(dev
, base
[id
], WS16C48_EXTENT
, name
)) {
317 dev_err(dev
, "Unable to lock port addresses (0x%X-0x%X)\n",
318 base
[id
], base
[id
] + WS16C48_EXTENT
);
322 ws16c48gpio
->chip
.label
= name
;
323 ws16c48gpio
->chip
.parent
= dev
;
324 ws16c48gpio
->chip
.owner
= THIS_MODULE
;
325 ws16c48gpio
->chip
.base
= -1;
326 ws16c48gpio
->chip
.ngpio
= 48;
327 ws16c48gpio
->chip
.get_direction
= ws16c48_gpio_get_direction
;
328 ws16c48gpio
->chip
.direction_input
= ws16c48_gpio_direction_input
;
329 ws16c48gpio
->chip
.direction_output
= ws16c48_gpio_direction_output
;
330 ws16c48gpio
->chip
.get
= ws16c48_gpio_get
;
331 ws16c48gpio
->chip
.set
= ws16c48_gpio_set
;
332 ws16c48gpio
->base
= base
[id
];
333 ws16c48gpio
->irq
= irq
[id
];
335 spin_lock_init(&ws16c48gpio
->lock
);
337 dev_set_drvdata(dev
, ws16c48gpio
);
339 err
= gpiochip_add_data(&ws16c48gpio
->chip
, ws16c48gpio
);
341 dev_err(dev
, "GPIO registering failed (%d)\n", err
);
345 /* Disable IRQ by default */
346 outb(0x80, base
[id
] + 7);
347 outb(0, base
[id
] + 8);
348 outb(0, base
[id
] + 9);
349 outb(0, base
[id
] + 10);
350 outb(0xC0, base
[id
] + 7);
352 err
= gpiochip_irqchip_add(&ws16c48gpio
->chip
, &ws16c48_irqchip
, 0,
353 handle_edge_irq
, IRQ_TYPE_NONE
);
355 dev_err(dev
, "Could not add irqchip (%d)\n", err
);
356 goto err_gpiochip_remove
;
359 err
= request_irq(irq
[id
], ws16c48_irq_handler
, IRQF_SHARED
, name
,
362 dev_err(dev
, "IRQ handler registering failed (%d)\n", err
);
363 goto err_gpiochip_remove
;
369 gpiochip_remove(&ws16c48gpio
->chip
);
373 static int ws16c48_remove(struct device
*dev
, unsigned int id
)
375 struct ws16c48_gpio
*const ws16c48gpio
= dev_get_drvdata(dev
);
377 free_irq(ws16c48gpio
->irq
, ws16c48gpio
);
378 gpiochip_remove(&ws16c48gpio
->chip
);
383 static struct isa_driver ws16c48_driver
= {
384 .probe
= ws16c48_probe
,
388 .remove
= ws16c48_remove
391 module_isa_driver(ws16c48_driver
, num_ws16c48
);
393 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
394 MODULE_DESCRIPTION("WinSystems WS16C48 GPIO driver");
395 MODULE_LICENSE("GPL v2");