2 * GPIO driver for the ACCES 104-IDIO-16 family
3 * Copyright (C) 2015 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/device.h>
15 #include <linux/errno.h>
16 #include <linux/gpio/driver.h>
18 #include <linux/ioport.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/moduleparam.h>
22 #include <linux/platform_device.h>
23 #include <linux/spinlock.h>
25 static unsigned idio_16_base
;
26 module_param(idio_16_base
, uint
, 0);
27 MODULE_PARM_DESC(idio_16_base
, "ACCES 104-IDIO-16 base address");
30 * struct idio_16_gpio - GPIO device private data structure
31 * @chip: instance of the gpio_chip
32 * @lock: synchronization lock to prevent gpio_set race conditions
33 * @base: base port address of the GPIO device
34 * @extent: extent of port address region of the GPIO device
35 * @out_state: output bits state
38 struct gpio_chip chip
;
45 static int idio_16_gpio_get_direction(struct gpio_chip
*chip
, unsigned offset
)
53 static int idio_16_gpio_direction_input(struct gpio_chip
*chip
, unsigned offset
)
58 static int idio_16_gpio_direction_output(struct gpio_chip
*chip
,
59 unsigned offset
, int value
)
61 chip
->set(chip
, offset
, value
);
65 static struct idio_16_gpio
*to_idio16gpio(struct gpio_chip
*gc
)
67 return container_of(gc
, struct idio_16_gpio
, chip
);
70 static int idio_16_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
72 struct idio_16_gpio
*const idio16gpio
= to_idio16gpio(chip
);
73 const unsigned BIT_MASK
= 1U << (offset
-16);
79 return !!(inb(idio16gpio
->base
+ 1) & BIT_MASK
);
81 return !!(inb(idio16gpio
->base
+ 5) & (BIT_MASK
>>8));
84 static void idio_16_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
86 struct idio_16_gpio
*const idio16gpio
= to_idio16gpio(chip
);
87 const unsigned BIT_MASK
= 1U << offset
;
93 spin_lock_irqsave(&idio16gpio
->lock
, flags
);
96 idio16gpio
->out_state
|= BIT_MASK
;
98 idio16gpio
->out_state
&= ~BIT_MASK
;
101 outb(idio16gpio
->out_state
>> 8, idio16gpio
->base
+ 4);
103 outb(idio16gpio
->out_state
, idio16gpio
->base
);
105 spin_unlock_irqrestore(&idio16gpio
->lock
, flags
);
108 static int __init
idio_16_probe(struct platform_device
*pdev
)
110 struct device
*dev
= &pdev
->dev
;
111 struct idio_16_gpio
*idio16gpio
;
114 const unsigned BASE
= idio_16_base
;
115 const unsigned EXTENT
= 8;
116 const char *const NAME
= dev_name(dev
);
118 idio16gpio
= devm_kzalloc(dev
, sizeof(*idio16gpio
), GFP_KERNEL
);
122 if (!request_region(BASE
, EXTENT
, NAME
)) {
123 dev_err(dev
, "Unable to lock %s port addresses (0x%X-0x%X)\n",
124 NAME
, BASE
, BASE
+ EXTENT
);
126 goto err_lock_io_port
;
129 idio16gpio
->chip
.label
= NAME
;
130 idio16gpio
->chip
.dev
= dev
;
131 idio16gpio
->chip
.owner
= THIS_MODULE
;
132 idio16gpio
->chip
.base
= -1;
133 idio16gpio
->chip
.ngpio
= 32;
134 idio16gpio
->chip
.get_direction
= idio_16_gpio_get_direction
;
135 idio16gpio
->chip
.direction_input
= idio_16_gpio_direction_input
;
136 idio16gpio
->chip
.direction_output
= idio_16_gpio_direction_output
;
137 idio16gpio
->chip
.get
= idio_16_gpio_get
;
138 idio16gpio
->chip
.set
= idio_16_gpio_set
;
139 idio16gpio
->base
= BASE
;
140 idio16gpio
->extent
= EXTENT
;
141 idio16gpio
->out_state
= 0xFFFF;
143 spin_lock_init(&idio16gpio
->lock
);
145 dev_set_drvdata(dev
, idio16gpio
);
147 err
= gpiochip_add(&idio16gpio
->chip
);
149 dev_err(dev
, "GPIO registering failed (%d)\n", err
);
150 goto err_gpio_register
;
156 release_region(BASE
, EXTENT
);
161 static int idio_16_remove(struct platform_device
*pdev
)
163 struct idio_16_gpio
*const idio16gpio
= platform_get_drvdata(pdev
);
165 gpiochip_remove(&idio16gpio
->chip
);
166 release_region(idio16gpio
->base
, idio16gpio
->extent
);
171 static struct platform_device
*idio_16_device
;
173 static struct platform_driver idio_16_driver
= {
175 .name
= "104-idio-16"
177 .remove
= idio_16_remove
180 static void __exit
idio_16_exit(void)
182 platform_device_unregister(idio_16_device
);
183 platform_driver_unregister(&idio_16_driver
);
186 static int __init
idio_16_init(void)
190 idio_16_device
= platform_device_alloc(idio_16_driver
.driver
.name
, -1);
194 err
= platform_device_add(idio_16_device
);
196 goto err_platform_device
;
198 err
= platform_driver_probe(&idio_16_driver
, idio_16_probe
);
200 goto err_platform_driver
;
205 platform_device_del(idio_16_device
);
207 platform_device_put(idio_16_device
);
211 module_init(idio_16_init
);
212 module_exit(idio_16_exit
);
214 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
215 MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
216 MODULE_LICENSE("GPL");