1 /* 2 * GPIO driver for the ACCES PCI-IDIO-16 3 * Copyright (C) 2017 William Breathitt Gray 4 * 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. 8 * 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. 13 */ 14 #include <linux/bitops.h> 15 #include <linux/device.h> 16 #include <linux/errno.h> 17 #include <linux/gpio/driver.h> 18 #include <linux/interrupt.h> 19 #include <linux/irqdesc.h> 20 #include <linux/kernel.h> 21 #include <linux/module.h> 22 #include <linux/pci.h> 23 #include <linux/spinlock.h> 24 #include <linux/types.h> 25 26 /** 27 * struct idio_16_gpio_reg - GPIO device registers structure 28 * @out0_7: Read: FET Drive Outputs 0-7 29 * Write: FET Drive Outputs 0-7 30 * @in0_7: Read: Isolated Inputs 0-7 31 * Write: Clear Interrupt 32 * @irq_ctl: Read: Enable IRQ 33 * Write: Disable IRQ 34 * @filter_ctl: Read: Activate Input Filters 0-15 35 * Write: Deactivate Input Filters 0-15 36 * @out8_15: Read: FET Drive Outputs 8-15 37 * Write: FET Drive Outputs 8-15 38 * @in8_15: Read: Isolated Inputs 8-15 39 * Write: Unused 40 * @irq_status: Read: Interrupt status 41 * Write: Unused 42 */ 43 struct idio_16_gpio_reg { 44 u8 out0_7; 45 u8 in0_7; 46 u8 irq_ctl; 47 u8 filter_ctl; 48 u8 out8_15; 49 u8 in8_15; 50 u8 irq_status; 51 }; 52 53 /** 54 * struct idio_16_gpio - GPIO device private data structure 55 * @chip: instance of the gpio_chip 56 * @lock: synchronization lock to prevent I/O race conditions 57 * @reg: I/O address offset for the GPIO device registers 58 * @irq_mask: I/O bits affected by interrupts 59 */ 60 struct idio_16_gpio { 61 struct gpio_chip chip; 62 spinlock_t lock; 63 struct idio_16_gpio_reg __iomem *reg; 64 unsigned long irq_mask; 65 }; 66 67 static int idio_16_gpio_get_direction(struct gpio_chip *chip, 68 unsigned int offset) 69 { 70 if (offset > 15) 71 return 1; 72 73 return 0; 74 } 75 76 static int idio_16_gpio_direction_input(struct gpio_chip *chip, 77 unsigned int offset) 78 { 79 return 0; 80 } 81 82 static int idio_16_gpio_direction_output(struct gpio_chip *chip, 83 unsigned int offset, int value) 84 { 85 chip->set(chip, offset, value); 86 return 0; 87 } 88 89 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) 90 { 91 struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); 92 unsigned long mask = BIT(offset); 93 94 if (offset < 8) 95 return !!(ioread8(&idio16gpio->reg->out0_7) & mask); 96 97 if (offset < 16) 98 return !!(ioread8(&idio16gpio->reg->out8_15) & (mask >> 8)); 99 100 if (offset < 24) 101 return !!(ioread8(&idio16gpio->reg->in0_7) & (mask >> 16)); 102 103 return !!(ioread8(&idio16gpio->reg->in8_15) & (mask >> 24)); 104 } 105 106 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, 107 int value) 108 { 109 struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); 110 unsigned int mask = BIT(offset); 111 void __iomem *base; 112 unsigned long flags; 113 unsigned int out_state; 114 115 if (offset > 15) 116 return; 117 118 if (offset > 7) { 119 mask >>= 8; 120 base = &idio16gpio->reg->out8_15; 121 } else 122 base = &idio16gpio->reg->out0_7; 123 124 spin_lock_irqsave(&idio16gpio->lock, flags); 125 126 if (value) 127 out_state = ioread8(base) | mask; 128 else 129 out_state = ioread8(base) & ~mask; 130 131 iowrite8(out_state, base); 132 133 spin_unlock_irqrestore(&idio16gpio->lock, flags); 134 } 135 136 static void idio_16_gpio_set_multiple(struct gpio_chip *chip, 137 unsigned long *mask, unsigned long *bits) 138 { 139 struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); 140 unsigned long flags; 141 unsigned int out_state; 142 143 spin_lock_irqsave(&idio16gpio->lock, flags); 144 145 /* process output lines 0-7 */ 146 if (*mask & 0xFF) { 147 out_state = ioread8(&idio16gpio->reg->out0_7) & ~*mask; 148 out_state |= *mask & *bits; 149 iowrite8(out_state, &idio16gpio->reg->out0_7); 150 } 151 152 /* shift to next output line word */ 153 *mask >>= 8; 154 155 /* process output lines 8-15 */ 156 if (*mask & 0xFF) { 157 *bits >>= 8; 158 out_state = ioread8(&idio16gpio->reg->out8_15) & ~*mask; 159 out_state |= *mask & *bits; 160 iowrite8(out_state, &idio16gpio->reg->out8_15); 161 } 162 163 spin_unlock_irqrestore(&idio16gpio->lock, flags); 164 } 165 166 static void idio_16_irq_ack(struct irq_data *data) 167 { 168 } 169 170 static void idio_16_irq_mask(struct irq_data *data) 171 { 172 struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 173 struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); 174 const unsigned long mask = BIT(irqd_to_hwirq(data)); 175 unsigned long flags; 176 177 idio16gpio->irq_mask &= ~mask; 178 179 if (!idio16gpio->irq_mask) { 180 spin_lock_irqsave(&idio16gpio->lock, flags); 181 182 iowrite8(0, &idio16gpio->reg->irq_ctl); 183 184 spin_unlock_irqrestore(&idio16gpio->lock, flags); 185 } 186 } 187 188 static void idio_16_irq_unmask(struct irq_data *data) 189 { 190 struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 191 struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); 192 const unsigned long mask = BIT(irqd_to_hwirq(data)); 193 const unsigned long prev_irq_mask = idio16gpio->irq_mask; 194 unsigned long flags; 195 196 idio16gpio->irq_mask |= mask; 197 198 if (!prev_irq_mask) { 199 spin_lock_irqsave(&idio16gpio->lock, flags); 200 201 ioread8(&idio16gpio->reg->irq_ctl); 202 203 spin_unlock_irqrestore(&idio16gpio->lock, flags); 204 } 205 } 206 207 static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type) 208 { 209 /* The only valid irq types are none and both-edges */ 210 if (flow_type != IRQ_TYPE_NONE && 211 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH) 212 return -EINVAL; 213 214 return 0; 215 } 216 217 static struct irq_chip idio_16_irqchip = { 218 .name = "pci-idio-16", 219 .irq_ack = idio_16_irq_ack, 220 .irq_mask = idio_16_irq_mask, 221 .irq_unmask = idio_16_irq_unmask, 222 .irq_set_type = idio_16_irq_set_type 223 }; 224 225 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) 226 { 227 struct idio_16_gpio *const idio16gpio = dev_id; 228 unsigned int irq_status; 229 struct gpio_chip *const chip = &idio16gpio->chip; 230 int gpio; 231 232 spin_lock(&idio16gpio->lock); 233 234 irq_status = ioread8(&idio16gpio->reg->irq_status); 235 236 spin_unlock(&idio16gpio->lock); 237 238 /* Make sure our device generated IRQ */ 239 if (!(irq_status & 0x3) || !(irq_status & 0x4)) 240 return IRQ_NONE; 241 242 for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio) 243 generic_handle_irq(irq_find_mapping(chip->irqdomain, gpio)); 244 245 spin_lock(&idio16gpio->lock); 246 247 /* Clear interrupt */ 248 iowrite8(0, &idio16gpio->reg->in0_7); 249 250 spin_unlock(&idio16gpio->lock); 251 252 return IRQ_HANDLED; 253 } 254 255 #define IDIO_16_NGPIO 32 256 static const char *idio_16_names[IDIO_16_NGPIO] = { 257 "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7", 258 "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15", 259 "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7", 260 "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15" 261 }; 262 263 static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id) 264 { 265 struct device *const dev = &pdev->dev; 266 struct idio_16_gpio *idio16gpio; 267 int err; 268 const char *const name = pci_name(pdev); 269 270 idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); 271 if (!idio16gpio) 272 return -ENOMEM; 273 274 err = pcim_enable_device(pdev); 275 if (err) { 276 dev_err(dev, "Failed to enable PCI device (%d)\n", err); 277 return err; 278 } 279 280 err = pcim_iomap_regions(pdev, 0x1, name); 281 if (err) { 282 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err); 283 return err; 284 } 285 286 idio16gpio->reg = pcim_iomap_table(pdev)[0]; 287 288 /* Deactivate input filters */ 289 iowrite8(0, &idio16gpio->reg->filter_ctl); 290 291 idio16gpio->chip.label = name; 292 idio16gpio->chip.parent = dev; 293 idio16gpio->chip.owner = THIS_MODULE; 294 idio16gpio->chip.base = -1; 295 idio16gpio->chip.ngpio = IDIO_16_NGPIO; 296 idio16gpio->chip.names = idio_16_names; 297 idio16gpio->chip.get_direction = idio_16_gpio_get_direction; 298 idio16gpio->chip.direction_input = idio_16_gpio_direction_input; 299 idio16gpio->chip.direction_output = idio_16_gpio_direction_output; 300 idio16gpio->chip.get = idio_16_gpio_get; 301 idio16gpio->chip.set = idio_16_gpio_set; 302 idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple; 303 304 spin_lock_init(&idio16gpio->lock); 305 306 err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); 307 if (err) { 308 dev_err(dev, "GPIO registering failed (%d)\n", err); 309 return err; 310 } 311 312 /* Disable IRQ by default and clear any pending interrupt */ 313 iowrite8(0, &idio16gpio->reg->irq_ctl); 314 iowrite8(0, &idio16gpio->reg->in0_7); 315 316 err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0, 317 handle_edge_irq, IRQ_TYPE_NONE); 318 if (err) { 319 dev_err(dev, "Could not add irqchip (%d)\n", err); 320 return err; 321 } 322 323 err = devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED, 324 name, idio16gpio); 325 if (err) { 326 dev_err(dev, "IRQ handler registering failed (%d)\n", err); 327 return err; 328 } 329 330 return 0; 331 } 332 333 static const struct pci_device_id idio_16_pci_dev_id[] = { 334 { PCI_DEVICE(0x494F, 0x0F00) }, { 0 } 335 }; 336 MODULE_DEVICE_TABLE(pci, idio_16_pci_dev_id); 337 338 static struct pci_driver idio_16_driver = { 339 .name = "pci-idio-16", 340 .id_table = idio_16_pci_dev_id, 341 .probe = idio_16_probe 342 }; 343 344 module_pci_driver(idio_16_driver); 345 346 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 347 MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver"); 348 MODULE_LICENSE("GPL v2"); 349