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 */ 65 struct 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 */ 91 struct 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 98 static 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 117 static 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 139 static 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 162 static 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 196 static 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 237 static void idio_24_irq_ack(struct irq_data *data) 238 { 239 } 240 241 static 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 270 static 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 299 static 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 309 static 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 317 static 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 354 static 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 364 static 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 430 static 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 }; 435 MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id); 436 437 static 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 443 module_pci_driver(idio_24_driver); 444 445 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 446 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver"); 447 MODULE_LICENSE("GPL v2"); 448