Merge tag 'pm-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
[linux-2.6-block.git] / drivers / gpio / gpio-pcie-idio-24.c
CommitLineData
58556204
WBG
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * GPIO driver for the ACCES PCIe-IDIO-24 family
4 * Copyright (C) 2018 William Breathitt Gray
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * This driver supports the following ACCES devices: PCIe-IDIO-24,
16 * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12.
17 */
18#include <linux/bitops.h>
19#include <linux/device.h>
20#include <linux/errno.h>
21#include <linux/gpio/driver.h>
22#include <linux/interrupt.h>
23#include <linux/irqdesc.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/pci.h>
27#include <linux/spinlock.h>
28#include <linux/types.h>
29
30/**
31 * struct idio_24_gpio_reg - GPIO device registers structure
32 * @out0_7: Read: FET Outputs 0-7
33 * Write: FET Outputs 0-7
34 * @out8_15: Read: FET Outputs 8-15
35 * Write: FET Outputs 8-15
36 * @out16_23: Read: FET Outputs 16-23
37 * Write: FET Outputs 16-23
38 * @ttl_out0_7: Read: TTL/CMOS Outputs 0-7
39 * Write: TTL/CMOS Outputs 0-7
40 * @in0_7: Read: Isolated Inputs 0-7
41 * Write: Reserved
42 * @in8_15: Read: Isolated Inputs 8-15
43 * Write: Reserved
44 * @in16_23: Read: Isolated Inputs 16-23
45 * Write: Reserved
46 * @ttl_in0_7: Read: TTL/CMOS Inputs 0-7
47 * Write: Reserved
48 * @cos0_7: Read: COS Status Inputs 0-7
49 * Write: COS Clear Inputs 0-7
50 * @cos8_15: Read: COS Status Inputs 8-15
51 * Write: COS Clear Inputs 8-15
52 * @cos16_23: Read: COS Status Inputs 16-23
53 * Write: COS Clear Inputs 16-23
54 * @cos_ttl0_7: Read: COS Status TTL/CMOS 0-7
55 * Write: COS Clear TTL/CMOS 0-7
56 * @ctl: Read: Control Register
57 * Write: Control Register
58 * @reserved: Read: Reserved
59 * Write: Reserved
60 * @cos_enable: Read: COS Enable
61 * Write: COS Enable
62 * @soft_reset: Read: IRQ Output Pin Status
63 * Write: Software Board Reset
64 */
65struct idio_24_gpio_reg {
66 u8 out0_7;
67 u8 out8_15;
68 u8 out16_23;
69 u8 ttl_out0_7;
70 u8 in0_7;
71 u8 in8_15;
72 u8 in16_23;
73 u8 ttl_in0_7;
74 u8 cos0_7;
75 u8 cos8_15;
76 u8 cos16_23;
77 u8 cos_ttl0_7;
78 u8 ctl;
79 u8 reserved;
80 u8 cos_enable;
81 u8 soft_reset;
82};
83
84/**
85 * struct idio_24_gpio - GPIO device private data structure
86 * @chip: instance of the gpio_chip
87 * @lock: synchronization lock to prevent I/O race conditions
88 * @reg: I/O address offset for the GPIO device registers
89 * @irq_mask: I/O bits affected by interrupts
90 */
91struct idio_24_gpio {
92 struct gpio_chip chip;
93 raw_spinlock_t lock;
94 struct idio_24_gpio_reg __iomem *reg;
95 unsigned long irq_mask;
96};
97
98static int idio_24_gpio_get_direction(struct gpio_chip *chip,
99 unsigned int offset)
100{
101 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
102 const unsigned long out_mode_mask = BIT(1);
103
104 /* FET Outputs */
105 if (offset < 24)
106 return 0;
107
108 /* Isolated Inputs */
109 if (offset < 48)
110 return 1;
111
112 /* TTL/CMOS I/O */
113 /* OUT MODE = 1 when TTL/CMOS Output Mode is set */
114 return !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask);
115}
116
117static int idio_24_gpio_direction_input(struct gpio_chip *chip,
118 unsigned int offset)
119{
120 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
121 unsigned long flags;
122 unsigned int ctl_state;
123 const unsigned long out_mode_mask = BIT(1);
124
125 /* TTL/CMOS I/O */
126 if (offset > 47) {
127 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
128
129 /* Clear TTL/CMOS Output Mode */
130 ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask;
131 iowrite8(ctl_state, &idio24gpio->reg->ctl);
132
133 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
134 }
135
136 return 0;
137}
138
139static int idio_24_gpio_direction_output(struct gpio_chip *chip,
140 unsigned int offset, int value)
141{
142 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
143 unsigned long flags;
144 unsigned int ctl_state;
145 const unsigned long out_mode_mask = BIT(1);
146
147 /* TTL/CMOS I/O */
148 if (offset > 47) {
149 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
150
151 /* Set TTL/CMOS Output Mode */
152 ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask;
153 iowrite8(ctl_state, &idio24gpio->reg->ctl);
154
155 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
156 }
157
158 chip->set(chip, offset, value);
159 return 0;
160}
161
162static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset)
163{
164 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
165 const unsigned long offset_mask = BIT(offset % 8);
166 const unsigned long out_mode_mask = BIT(1);
167
168 /* FET Outputs */
169 if (offset < 8)
170 return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask);
171
172 if (offset < 16)
173 return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask);
174
175 if (offset < 24)
176 return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask);
177
178 /* Isolated Inputs */
179 if (offset < 32)
180 return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask);
181
182 if (offset < 40)
183 return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask);
184
185 if (offset < 48)
186 return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask);
187
188 /* TTL/CMOS Outputs */
189 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
190 return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask);
191
192 /* TTL/CMOS Inputs */
193 return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask);
194}
195
196static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset,
197 int value)
198{
199 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
200 const unsigned long out_mode_mask = BIT(1);
201 void __iomem *base;
202 const unsigned int mask = BIT(offset % 8);
203 unsigned long flags;
204 unsigned int out_state;
205
206 /* Isolated Inputs */
207 if (offset > 23 && offset < 48)
208 return;
209
210 /* TTL/CMOS Inputs */
211 if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask))
212 return;
213
214 /* TTL/CMOS Outputs */
215 if (offset > 47)
216 base = &idio24gpio->reg->ttl_out0_7;
217 /* FET Outputs */
218 else if (offset > 15)
219 base = &idio24gpio->reg->out16_23;
220 else if (offset > 7)
221 base = &idio24gpio->reg->out8_15;
222 else
223 base = &idio24gpio->reg->out0_7;
224
225 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
226
227 if (value)
228 out_state = ioread8(base) | mask;
229 else
230 out_state = ioread8(base) & ~mask;
231
232 iowrite8(out_state, base);
233
234 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
235}
236
237static void idio_24_irq_ack(struct irq_data *data)
238{
239}
240
241static void idio_24_irq_mask(struct irq_data *data)
242{
243 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
244 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
245 unsigned long flags;
246 const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
247 unsigned char new_irq_mask;
248 const unsigned long bank_offset = bit_offset/8 * 8;
249 unsigned char cos_enable_state;
250
251 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
252
253 idio24gpio->irq_mask &= BIT(bit_offset);
254 new_irq_mask = idio24gpio->irq_mask >> bank_offset;
255
256 if (!new_irq_mask) {
257 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
258
259 /* Disable Rising Edge detection */
260 cos_enable_state &= ~BIT(bank_offset);
261 /* Disable Falling Edge detection */
262 cos_enable_state &= ~BIT(bank_offset + 4);
263
264 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
265 }
266
267 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
268}
269
270static void idio_24_irq_unmask(struct irq_data *data)
271{
272 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data);
273 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
274 unsigned long flags;
275 unsigned char prev_irq_mask;
276 const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
277 const unsigned long bank_offset = bit_offset/8 * 8;
278 unsigned char cos_enable_state;
279
280 raw_spin_lock_irqsave(&idio24gpio->lock, flags);
281
282 prev_irq_mask = idio24gpio->irq_mask >> bank_offset;
283 idio24gpio->irq_mask |= BIT(bit_offset);
284
285 if (!prev_irq_mask) {
286 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
287
288 /* Enable Rising Edge detection */
289 cos_enable_state |= BIT(bank_offset);
290 /* Enable Falling Edge detection */
291 cos_enable_state |= BIT(bank_offset + 4);
292
293 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable);
294 }
295
296 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
297}
298
299static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type)
300{
301 /* The only valid irq types are none and both-edges */
302 if (flow_type != IRQ_TYPE_NONE &&
303 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
304 return -EINVAL;
305
306 return 0;
307}
308
309static struct irq_chip idio_24_irqchip = {
310 .name = "pcie-idio-24",
311 .irq_ack = idio_24_irq_ack,
312 .irq_mask = idio_24_irq_mask,
313 .irq_unmask = idio_24_irq_unmask,
314 .irq_set_type = idio_24_irq_set_type
315};
316
317static irqreturn_t idio_24_irq_handler(int irq, void *dev_id)
318{
319 struct idio_24_gpio *const idio24gpio = dev_id;
320 unsigned long irq_status;
321 struct gpio_chip *const chip = &idio24gpio->chip;
322 unsigned long irq_mask;
323 int gpio;
324
325 raw_spin_lock(&idio24gpio->lock);
326
327 /* Read Change-Of-State status */
328 irq_status = ioread32(&idio24gpio->reg->cos0_7);
329
330 raw_spin_unlock(&idio24gpio->lock);
331
332 /* Make sure our device generated IRQ */
333 if (!irq_status)
334 return IRQ_NONE;
335
336 /* Handle only unmasked IRQ */
337 irq_mask = idio24gpio->irq_mask & irq_status;
338
339 for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24)
340 generic_handle_irq(irq_find_mapping(chip->irq.domain,
341 gpio + 24));
342
343 raw_spin_lock(&idio24gpio->lock);
344
345 /* Clear Change-Of-State status */
346 iowrite32(irq_status, &idio24gpio->reg->cos0_7);
347
348 raw_spin_unlock(&idio24gpio->lock);
349
350 return IRQ_HANDLED;
351}
352
353#define IDIO_24_NGPIO 56
354static const char *idio_24_names[IDIO_24_NGPIO] = {
355 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
356 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
357 "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
358 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
359 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
360 "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
361 "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
362};
363
364static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
365{
366 struct device *const dev = &pdev->dev;
367 struct idio_24_gpio *idio24gpio;
368 int err;
369 const size_t pci_bar_index = 2;
370 const char *const name = pci_name(pdev);
371
372 idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
373 if (!idio24gpio)
374 return -ENOMEM;
375
376 err = pcim_enable_device(pdev);
377 if (err) {
378 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
379 return err;
380 }
381
382 err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
383 if (err) {
384 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
385 return err;
386 }
387
388 idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
389
390 idio24gpio->chip.label = name;
391 idio24gpio->chip.parent = dev;
392 idio24gpio->chip.owner = THIS_MODULE;
393 idio24gpio->chip.base = -1;
394 idio24gpio->chip.ngpio = IDIO_24_NGPIO;
395 idio24gpio->chip.names = idio_24_names;
396 idio24gpio->chip.get_direction = idio_24_gpio_get_direction;
397 idio24gpio->chip.direction_input = idio_24_gpio_direction_input;
398 idio24gpio->chip.direction_output = idio_24_gpio_direction_output;
399 idio24gpio->chip.get = idio_24_gpio_get;
400 idio24gpio->chip.set = idio_24_gpio_set;
401
402 raw_spin_lock_init(&idio24gpio->lock);
403
404 /* Software board reset */
405 iowrite8(0, &idio24gpio->reg->soft_reset);
406
407 err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
408 if (err) {
409 dev_err(dev, "GPIO registering failed (%d)\n", err);
410 return err;
411 }
412
413 err = gpiochip_irqchip_add(&idio24gpio->chip, &idio_24_irqchip, 0,
414 handle_edge_irq, IRQ_TYPE_NONE);
415 if (err) {
416 dev_err(dev, "Could not add irqchip (%d)\n", err);
417 return err;
418 }
419
420 err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED,
421 name, idio24gpio);
422 if (err) {
423 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
424 return err;
425 }
426
427 return 0;
428}
429
430static const struct pci_device_id idio_24_pci_dev_id[] = {
431 { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
432 { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
433 { 0 }
434};
435MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
436
437static struct pci_driver idio_24_driver = {
438 .name = "pcie-idio-24",
439 .id_table = idio_24_pci_dev_id,
440 .probe = idio_24_probe
441};
442
443module_pci_driver(idio_24_driver);
444
445MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
446MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
447MODULE_LICENSE("GPL v2");