gpio-pci-idio-16.c 9.0 KB

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