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/bitmap.h> 19 #include <linux/bitops.h> 20 #include <linux/device.h> 21 #include <linux/errno.h> 22 #include <linux/gpio/driver.h> 23 #include <linux/interrupt.h> 24 #include <linux/irqdesc.h> 25 #include <linux/kernel.h> 26 #include <linux/module.h> 27 #include <linux/pci.h> 28 #include <linux/spinlock.h> 29 #include <linux/types.h> 30 31 /** 32 * struct idio_24_gpio_reg - GPIO device registers structure 33 * @out0_7: Read: FET Outputs 0-7 34 * Write: FET Outputs 0-7 35 * @out8_15: Read: FET Outputs 8-15 36 * Write: FET Outputs 8-15 37 * @out16_23: Read: FET Outputs 16-23 38 * Write: FET Outputs 16-23 39 * @ttl_out0_7: Read: TTL/CMOS Outputs 0-7 40 * Write: TTL/CMOS Outputs 0-7 41 * @in0_7: Read: Isolated Inputs 0-7 42 * Write: Reserved 43 * @in8_15: Read: Isolated Inputs 8-15 44 * Write: Reserved 45 * @in16_23: Read: Isolated Inputs 16-23 46 * Write: Reserved 47 * @ttl_in0_7: Read: TTL/CMOS Inputs 0-7 48 * Write: Reserved 49 * @cos0_7: Read: COS Status Inputs 0-7 50 * Write: COS Clear Inputs 0-7 51 * @cos8_15: Read: COS Status Inputs 8-15 52 * Write: COS Clear Inputs 8-15 53 * @cos16_23: Read: COS Status Inputs 16-23 54 * Write: COS Clear Inputs 16-23 55 * @cos_ttl0_7: Read: COS Status TTL/CMOS 0-7 56 * Write: COS Clear TTL/CMOS 0-7 57 * @ctl: Read: Control Register 58 * Write: Control Register 59 * @reserved: Read: Reserved 60 * Write: Reserved 61 * @cos_enable: Read: COS Enable 62 * Write: COS Enable 63 * @soft_reset: Read: IRQ Output Pin Status 64 * Write: Software Board Reset 65 */ 66 struct idio_24_gpio_reg { 67 u8 out0_7; 68 u8 out8_15; 69 u8 out16_23; 70 u8 ttl_out0_7; 71 u8 in0_7; 72 u8 in8_15; 73 u8 in16_23; 74 u8 ttl_in0_7; 75 u8 cos0_7; 76 u8 cos8_15; 77 u8 cos16_23; 78 u8 cos_ttl0_7; 79 u8 ctl; 80 u8 reserved; 81 u8 cos_enable; 82 u8 soft_reset; 83 }; 84 85 /** 86 * struct idio_24_gpio - GPIO device private data structure 87 * @chip: instance of the gpio_chip 88 * @lock: synchronization lock to prevent I/O race conditions 89 * @reg: I/O address offset for the GPIO device registers 90 * @irq_mask: I/O bits affected by interrupts 91 */ 92 struct idio_24_gpio { 93 struct gpio_chip chip; 94 raw_spinlock_t lock; 95 struct idio_24_gpio_reg __iomem *reg; 96 unsigned long irq_mask; 97 }; 98 99 static int idio_24_gpio_get_direction(struct gpio_chip *chip, 100 unsigned int offset) 101 { 102 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 103 const unsigned long out_mode_mask = BIT(1); 104 105 /* FET Outputs */ 106 if (offset < 24) 107 return GPIO_LINE_DIRECTION_OUT; 108 109 /* Isolated Inputs */ 110 if (offset < 48) 111 return GPIO_LINE_DIRECTION_IN; 112 113 /* TTL/CMOS I/O */ 114 /* OUT MODE = 1 when TTL/CMOS Output Mode is set */ 115 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) 116 return GPIO_LINE_DIRECTION_OUT; 117 118 return GPIO_LINE_DIRECTION_IN; 119 } 120 121 static int idio_24_gpio_direction_input(struct gpio_chip *chip, 122 unsigned int offset) 123 { 124 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 125 unsigned long flags; 126 unsigned int ctl_state; 127 const unsigned long out_mode_mask = BIT(1); 128 129 /* TTL/CMOS I/O */ 130 if (offset > 47) { 131 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 132 133 /* Clear TTL/CMOS Output Mode */ 134 ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask; 135 iowrite8(ctl_state, &idio24gpio->reg->ctl); 136 137 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 138 } 139 140 return 0; 141 } 142 143 static int idio_24_gpio_direction_output(struct gpio_chip *chip, 144 unsigned int offset, int value) 145 { 146 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 147 unsigned long flags; 148 unsigned int ctl_state; 149 const unsigned long out_mode_mask = BIT(1); 150 151 /* TTL/CMOS I/O */ 152 if (offset > 47) { 153 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 154 155 /* Set TTL/CMOS Output Mode */ 156 ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask; 157 iowrite8(ctl_state, &idio24gpio->reg->ctl); 158 159 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 160 } 161 162 chip->set(chip, offset, value); 163 return 0; 164 } 165 166 static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset) 167 { 168 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 169 const unsigned long offset_mask = BIT(offset % 8); 170 const unsigned long out_mode_mask = BIT(1); 171 172 /* FET Outputs */ 173 if (offset < 8) 174 return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask); 175 176 if (offset < 16) 177 return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask); 178 179 if (offset < 24) 180 return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask); 181 182 /* Isolated Inputs */ 183 if (offset < 32) 184 return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask); 185 186 if (offset < 40) 187 return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask); 188 189 if (offset < 48) 190 return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask); 191 192 /* TTL/CMOS Outputs */ 193 if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) 194 return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask); 195 196 /* TTL/CMOS Inputs */ 197 return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask); 198 } 199 200 static int idio_24_gpio_get_multiple(struct gpio_chip *chip, 201 unsigned long *mask, unsigned long *bits) 202 { 203 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 204 unsigned long offset; 205 unsigned long gpio_mask; 206 void __iomem *ports[] = { 207 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15, 208 &idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7, 209 &idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23, 210 }; 211 size_t index; 212 unsigned long port_state; 213 const unsigned long out_mode_mask = BIT(1); 214 215 /* clear bits array to a clean slate */ 216 bitmap_zero(bits, chip->ngpio); 217 218 for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { 219 index = offset / 8; 220 221 /* read bits from current gpio port (port 6 is TTL GPIO) */ 222 if (index < 6) 223 port_state = ioread8(ports[index]); 224 else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) 225 port_state = ioread8(&idio24gpio->reg->ttl_out0_7); 226 else 227 port_state = ioread8(&idio24gpio->reg->ttl_in0_7); 228 229 port_state &= gpio_mask; 230 231 bitmap_set_value8(bits, port_state, offset); 232 } 233 234 return 0; 235 } 236 237 static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset, 238 int value) 239 { 240 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 241 const unsigned long out_mode_mask = BIT(1); 242 void __iomem *base; 243 const unsigned int mask = BIT(offset % 8); 244 unsigned long flags; 245 unsigned int out_state; 246 247 /* Isolated Inputs */ 248 if (offset > 23 && offset < 48) 249 return; 250 251 /* TTL/CMOS Inputs */ 252 if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask)) 253 return; 254 255 /* TTL/CMOS Outputs */ 256 if (offset > 47) 257 base = &idio24gpio->reg->ttl_out0_7; 258 /* FET Outputs */ 259 else if (offset > 15) 260 base = &idio24gpio->reg->out16_23; 261 else if (offset > 7) 262 base = &idio24gpio->reg->out8_15; 263 else 264 base = &idio24gpio->reg->out0_7; 265 266 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 267 268 if (value) 269 out_state = ioread8(base) | mask; 270 else 271 out_state = ioread8(base) & ~mask; 272 273 iowrite8(out_state, base); 274 275 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 276 } 277 278 static void idio_24_gpio_set_multiple(struct gpio_chip *chip, 279 unsigned long *mask, unsigned long *bits) 280 { 281 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 282 unsigned long offset; 283 unsigned long gpio_mask; 284 void __iomem *ports[] = { 285 &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15, 286 &idio24gpio->reg->out16_23 287 }; 288 size_t index; 289 unsigned long bitmask; 290 unsigned long flags; 291 unsigned long out_state; 292 const unsigned long out_mode_mask = BIT(1); 293 294 for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { 295 index = offset / 8; 296 297 bitmask = bitmap_get_value8(bits, offset) & gpio_mask; 298 299 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 300 301 /* read bits from current gpio port (port 6 is TTL GPIO) */ 302 if (index < 6) { 303 out_state = ioread8(ports[index]); 304 } else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) { 305 out_state = ioread8(&idio24gpio->reg->ttl_out0_7); 306 } else { 307 /* skip TTL GPIO if set for input */ 308 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 309 continue; 310 } 311 312 /* set requested bit states */ 313 out_state &= ~gpio_mask; 314 out_state |= bitmask; 315 316 /* write bits for current gpio port (port 6 is TTL GPIO) */ 317 if (index < 6) 318 iowrite8(out_state, ports[index]); 319 else 320 iowrite8(out_state, &idio24gpio->reg->ttl_out0_7); 321 322 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 323 } 324 } 325 326 static void idio_24_irq_ack(struct irq_data *data) 327 { 328 } 329 330 static void idio_24_irq_mask(struct irq_data *data) 331 { 332 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data); 333 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 334 unsigned long flags; 335 const unsigned long bit_offset = irqd_to_hwirq(data) - 24; 336 unsigned char new_irq_mask; 337 const unsigned long bank_offset = bit_offset/8 * 8; 338 unsigned char cos_enable_state; 339 340 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 341 342 idio24gpio->irq_mask &= BIT(bit_offset); 343 new_irq_mask = idio24gpio->irq_mask >> bank_offset; 344 345 if (!new_irq_mask) { 346 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable); 347 348 /* Disable Rising Edge detection */ 349 cos_enable_state &= ~BIT(bank_offset); 350 /* Disable Falling Edge detection */ 351 cos_enable_state &= ~BIT(bank_offset + 4); 352 353 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable); 354 } 355 356 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 357 } 358 359 static void idio_24_irq_unmask(struct irq_data *data) 360 { 361 struct gpio_chip *const chip = irq_data_get_irq_chip_data(data); 362 struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); 363 unsigned long flags; 364 unsigned char prev_irq_mask; 365 const unsigned long bit_offset = irqd_to_hwirq(data) - 24; 366 const unsigned long bank_offset = bit_offset/8 * 8; 367 unsigned char cos_enable_state; 368 369 raw_spin_lock_irqsave(&idio24gpio->lock, flags); 370 371 prev_irq_mask = idio24gpio->irq_mask >> bank_offset; 372 idio24gpio->irq_mask |= BIT(bit_offset); 373 374 if (!prev_irq_mask) { 375 cos_enable_state = ioread8(&idio24gpio->reg->cos_enable); 376 377 /* Enable Rising Edge detection */ 378 cos_enable_state |= BIT(bank_offset); 379 /* Enable Falling Edge detection */ 380 cos_enable_state |= BIT(bank_offset + 4); 381 382 iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable); 383 } 384 385 raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); 386 } 387 388 static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type) 389 { 390 /* The only valid irq types are none and both-edges */ 391 if (flow_type != IRQ_TYPE_NONE && 392 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH) 393 return -EINVAL; 394 395 return 0; 396 } 397 398 static struct irq_chip idio_24_irqchip = { 399 .name = "pcie-idio-24", 400 .irq_ack = idio_24_irq_ack, 401 .irq_mask = idio_24_irq_mask, 402 .irq_unmask = idio_24_irq_unmask, 403 .irq_set_type = idio_24_irq_set_type 404 }; 405 406 static irqreturn_t idio_24_irq_handler(int irq, void *dev_id) 407 { 408 struct idio_24_gpio *const idio24gpio = dev_id; 409 unsigned long irq_status; 410 struct gpio_chip *const chip = &idio24gpio->chip; 411 unsigned long irq_mask; 412 int gpio; 413 414 raw_spin_lock(&idio24gpio->lock); 415 416 /* Read Change-Of-State status */ 417 irq_status = ioread32(&idio24gpio->reg->cos0_7); 418 419 raw_spin_unlock(&idio24gpio->lock); 420 421 /* Make sure our device generated IRQ */ 422 if (!irq_status) 423 return IRQ_NONE; 424 425 /* Handle only unmasked IRQ */ 426 irq_mask = idio24gpio->irq_mask & irq_status; 427 428 for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24) 429 generic_handle_irq(irq_find_mapping(chip->irq.domain, 430 gpio + 24)); 431 432 raw_spin_lock(&idio24gpio->lock); 433 434 /* Clear Change-Of-State status */ 435 iowrite32(irq_status, &idio24gpio->reg->cos0_7); 436 437 raw_spin_unlock(&idio24gpio->lock); 438 439 return IRQ_HANDLED; 440 } 441 442 #define IDIO_24_NGPIO 56 443 static const char *idio_24_names[IDIO_24_NGPIO] = { 444 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7", 445 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15", 446 "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23", 447 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7", 448 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15", 449 "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23", 450 "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7" 451 }; 452 453 static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) 454 { 455 struct device *const dev = &pdev->dev; 456 struct idio_24_gpio *idio24gpio; 457 int err; 458 const size_t pci_bar_index = 2; 459 const char *const name = pci_name(pdev); 460 struct gpio_irq_chip *girq; 461 462 idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL); 463 if (!idio24gpio) 464 return -ENOMEM; 465 466 err = pcim_enable_device(pdev); 467 if (err) { 468 dev_err(dev, "Failed to enable PCI device (%d)\n", err); 469 return err; 470 } 471 472 err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name); 473 if (err) { 474 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err); 475 return err; 476 } 477 478 idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index]; 479 480 idio24gpio->chip.label = name; 481 idio24gpio->chip.parent = dev; 482 idio24gpio->chip.owner = THIS_MODULE; 483 idio24gpio->chip.base = -1; 484 idio24gpio->chip.ngpio = IDIO_24_NGPIO; 485 idio24gpio->chip.names = idio_24_names; 486 idio24gpio->chip.get_direction = idio_24_gpio_get_direction; 487 idio24gpio->chip.direction_input = idio_24_gpio_direction_input; 488 idio24gpio->chip.direction_output = idio_24_gpio_direction_output; 489 idio24gpio->chip.get = idio_24_gpio_get; 490 idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple; 491 idio24gpio->chip.set = idio_24_gpio_set; 492 idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple; 493 494 girq = &idio24gpio->chip.irq; 495 girq->chip = &idio_24_irqchip; 496 /* This will let us handle the parent IRQ in the driver */ 497 girq->parent_handler = NULL; 498 girq->num_parents = 0; 499 girq->parents = NULL; 500 girq->default_type = IRQ_TYPE_NONE; 501 girq->handler = handle_edge_irq; 502 503 raw_spin_lock_init(&idio24gpio->lock); 504 505 /* Software board reset */ 506 iowrite8(0, &idio24gpio->reg->soft_reset); 507 508 err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio); 509 if (err) { 510 dev_err(dev, "GPIO registering failed (%d)\n", err); 511 return err; 512 } 513 514 err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED, 515 name, idio24gpio); 516 if (err) { 517 dev_err(dev, "IRQ handler registering failed (%d)\n", err); 518 return err; 519 } 520 521 return 0; 522 } 523 524 static const struct pci_device_id idio_24_pci_dev_id[] = { 525 { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) }, 526 { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) }, 527 { 0 } 528 }; 529 MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id); 530 531 static struct pci_driver idio_24_driver = { 532 .name = "pcie-idio-24", 533 .id_table = idio_24_pci_dev_id, 534 .probe = idio_24_probe 535 }; 536 537 module_pci_driver(idio_24_driver); 538 539 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 540 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver"); 541 MODULE_LICENSE("GPL v2"); 542