gpio-104-dio-48e.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. * GPIO driver for the ACCES 104-DIO-48E
  3. * Copyright (C) 2016 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/io.h>
  19. #include <linux/ioport.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/irqdesc.h>
  22. #include <linux/kernel.h>
  23. #include <linux/module.h>
  24. #include <linux/moduleparam.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/spinlock.h>
  27. static unsigned dio_48e_base;
  28. module_param(dio_48e_base, uint, 0);
  29. MODULE_PARM_DESC(dio_48e_base, "ACCES 104-DIO-48E base address");
  30. static unsigned dio_48e_irq;
  31. module_param(dio_48e_irq, uint, 0);
  32. MODULE_PARM_DESC(dio_48e_irq, "ACCES 104-DIO-48E interrupt line number");
  33. /**
  34. * struct dio48e_gpio - GPIO device private data structure
  35. * @chip: instance of the gpio_chip
  36. * @io_state: bit I/O state (whether bit is set to input or output)
  37. * @out_state: output bits state
  38. * @control: Control registers state
  39. * @lock: synchronization lock to prevent I/O race conditions
  40. * @base: base port address of the GPIO device
  41. * @irq: Interrupt line number
  42. * @irq_mask: I/O bits affected by interrupts
  43. */
  44. struct dio48e_gpio {
  45. struct gpio_chip chip;
  46. unsigned char io_state[6];
  47. unsigned char out_state[6];
  48. unsigned char control[2];
  49. spinlock_t lock;
  50. unsigned base;
  51. unsigned irq;
  52. unsigned char irq_mask;
  53. };
  54. static int dio48e_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
  55. {
  56. struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
  57. const unsigned port = offset / 8;
  58. const unsigned mask = BIT(offset % 8);
  59. return !!(dio48egpio->io_state[port] & mask);
  60. }
  61. static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
  62. {
  63. struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
  64. const unsigned io_port = offset / 8;
  65. const unsigned control_port = io_port / 2;
  66. const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
  67. unsigned long flags;
  68. unsigned control;
  69. spin_lock_irqsave(&dio48egpio->lock, flags);
  70. /* Check if configuring Port C */
  71. if (io_port == 2 || io_port == 5) {
  72. /* Port C can be configured by nibble */
  73. if (offset % 8 > 3) {
  74. dio48egpio->io_state[io_port] |= 0xF0;
  75. dio48egpio->control[control_port] |= BIT(3);
  76. } else {
  77. dio48egpio->io_state[io_port] |= 0x0F;
  78. dio48egpio->control[control_port] |= BIT(0);
  79. }
  80. } else {
  81. dio48egpio->io_state[io_port] |= 0xFF;
  82. if (io_port == 0 || io_port == 3)
  83. dio48egpio->control[control_port] |= BIT(4);
  84. else
  85. dio48egpio->control[control_port] |= BIT(1);
  86. }
  87. control = BIT(7) | dio48egpio->control[control_port];
  88. outb(control, control_addr);
  89. control &= ~BIT(7);
  90. outb(control, control_addr);
  91. spin_unlock_irqrestore(&dio48egpio->lock, flags);
  92. return 0;
  93. }
  94. static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
  95. int value)
  96. {
  97. struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
  98. const unsigned io_port = offset / 8;
  99. const unsigned control_port = io_port / 2;
  100. const unsigned mask = BIT(offset % 8);
  101. const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
  102. const unsigned out_port = (io_port > 2) ? io_port + 1 : io_port;
  103. unsigned long flags;
  104. unsigned control;
  105. spin_lock_irqsave(&dio48egpio->lock, flags);
  106. /* Check if configuring Port C */
  107. if (io_port == 2 || io_port == 5) {
  108. /* Port C can be configured by nibble */
  109. if (offset % 8 > 3) {
  110. dio48egpio->io_state[io_port] &= 0x0F;
  111. dio48egpio->control[control_port] &= ~BIT(3);
  112. } else {
  113. dio48egpio->io_state[io_port] &= 0xF0;
  114. dio48egpio->control[control_port] &= ~BIT(0);
  115. }
  116. } else {
  117. dio48egpio->io_state[io_port] &= 0x00;
  118. if (io_port == 0 || io_port == 3)
  119. dio48egpio->control[control_port] &= ~BIT(4);
  120. else
  121. dio48egpio->control[control_port] &= ~BIT(1);
  122. }
  123. if (value)
  124. dio48egpio->out_state[io_port] |= mask;
  125. else
  126. dio48egpio->out_state[io_port] &= ~mask;
  127. control = BIT(7) | dio48egpio->control[control_port];
  128. outb(control, control_addr);
  129. outb(dio48egpio->out_state[io_port], dio48egpio->base + out_port);
  130. control &= ~BIT(7);
  131. outb(control, control_addr);
  132. spin_unlock_irqrestore(&dio48egpio->lock, flags);
  133. return 0;
  134. }
  135. static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset)
  136. {
  137. struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
  138. const unsigned port = offset / 8;
  139. const unsigned mask = BIT(offset % 8);
  140. const unsigned in_port = (port > 2) ? port + 1 : port;
  141. unsigned long flags;
  142. unsigned port_state;
  143. spin_lock_irqsave(&dio48egpio->lock, flags);
  144. /* ensure that GPIO is set for input */
  145. if (!(dio48egpio->io_state[port] & mask)) {
  146. spin_unlock_irqrestore(&dio48egpio->lock, flags);
  147. return -EINVAL;
  148. }
  149. port_state = inb(dio48egpio->base + in_port);
  150. spin_unlock_irqrestore(&dio48egpio->lock, flags);
  151. return !!(port_state & mask);
  152. }
  153. static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
  154. {
  155. struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
  156. const unsigned port = offset / 8;
  157. const unsigned mask = BIT(offset % 8);
  158. const unsigned out_port = (port > 2) ? port + 1 : port;
  159. unsigned long flags;
  160. spin_lock_irqsave(&dio48egpio->lock, flags);
  161. if (value)
  162. dio48egpio->out_state[port] |= mask;
  163. else
  164. dio48egpio->out_state[port] &= ~mask;
  165. outb(dio48egpio->out_state[port], dio48egpio->base + out_port);
  166. spin_unlock_irqrestore(&dio48egpio->lock, flags);
  167. }
  168. static void dio48e_irq_ack(struct irq_data *data)
  169. {
  170. }
  171. static void dio48e_irq_mask(struct irq_data *data)
  172. {
  173. struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
  174. struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
  175. const unsigned long offset = irqd_to_hwirq(data);
  176. unsigned long flags;
  177. /* only bit 3 on each respective Port C supports interrupts */
  178. if (offset != 19 && offset != 43)
  179. return;
  180. spin_lock_irqsave(&dio48egpio->lock, flags);
  181. if (offset == 19)
  182. dio48egpio->irq_mask &= ~BIT(0);
  183. else
  184. dio48egpio->irq_mask &= ~BIT(1);
  185. if (!dio48egpio->irq_mask)
  186. /* disable interrupts */
  187. inb(dio48egpio->base + 0xB);
  188. spin_unlock_irqrestore(&dio48egpio->lock, flags);
  189. }
  190. static void dio48e_irq_unmask(struct irq_data *data)
  191. {
  192. struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
  193. struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
  194. const unsigned long offset = irqd_to_hwirq(data);
  195. unsigned long flags;
  196. /* only bit 3 on each respective Port C supports interrupts */
  197. if (offset != 19 && offset != 43)
  198. return;
  199. spin_lock_irqsave(&dio48egpio->lock, flags);
  200. if (!dio48egpio->irq_mask) {
  201. /* enable interrupts */
  202. outb(0x00, dio48egpio->base + 0xF);
  203. outb(0x00, dio48egpio->base + 0xB);
  204. }
  205. if (offset == 19)
  206. dio48egpio->irq_mask |= BIT(0);
  207. else
  208. dio48egpio->irq_mask |= BIT(1);
  209. spin_unlock_irqrestore(&dio48egpio->lock, flags);
  210. }
  211. static int dio48e_irq_set_type(struct irq_data *data, unsigned flow_type)
  212. {
  213. const unsigned long offset = irqd_to_hwirq(data);
  214. /* only bit 3 on each respective Port C supports interrupts */
  215. if (offset != 19 && offset != 43)
  216. return -EINVAL;
  217. if (flow_type != IRQ_TYPE_NONE && flow_type != IRQ_TYPE_EDGE_RISING)
  218. return -EINVAL;
  219. return 0;
  220. }
  221. static struct irq_chip dio48e_irqchip = {
  222. .name = "104-dio-48e",
  223. .irq_ack = dio48e_irq_ack,
  224. .irq_mask = dio48e_irq_mask,
  225. .irq_unmask = dio48e_irq_unmask,
  226. .irq_set_type = dio48e_irq_set_type
  227. };
  228. static irqreturn_t dio48e_irq_handler(int irq, void *dev_id)
  229. {
  230. struct dio48e_gpio *const dio48egpio = dev_id;
  231. struct gpio_chip *const chip = &dio48egpio->chip;
  232. const unsigned long irq_mask = dio48egpio->irq_mask;
  233. unsigned long gpio;
  234. for_each_set_bit(gpio, &irq_mask, 2)
  235. generic_handle_irq(irq_find_mapping(chip->irqdomain,
  236. 19 + gpio*24));
  237. spin_lock(&dio48egpio->lock);
  238. outb(0x00, dio48egpio->base + 0xF);
  239. spin_unlock(&dio48egpio->lock);
  240. return IRQ_HANDLED;
  241. }
  242. static int __init dio48e_probe(struct platform_device *pdev)
  243. {
  244. struct device *dev = &pdev->dev;
  245. struct dio48e_gpio *dio48egpio;
  246. const unsigned base = dio_48e_base;
  247. const unsigned extent = 16;
  248. const char *const name = dev_name(dev);
  249. int err;
  250. const unsigned irq = dio_48e_irq;
  251. dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL);
  252. if (!dio48egpio)
  253. return -ENOMEM;
  254. if (!devm_request_region(dev, base, extent, name)) {
  255. dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
  256. base, base + extent);
  257. return -EBUSY;
  258. }
  259. dio48egpio->chip.label = name;
  260. dio48egpio->chip.parent = dev;
  261. dio48egpio->chip.owner = THIS_MODULE;
  262. dio48egpio->chip.base = -1;
  263. dio48egpio->chip.ngpio = 48;
  264. dio48egpio->chip.get_direction = dio48e_gpio_get_direction;
  265. dio48egpio->chip.direction_input = dio48e_gpio_direction_input;
  266. dio48egpio->chip.direction_output = dio48e_gpio_direction_output;
  267. dio48egpio->chip.get = dio48e_gpio_get;
  268. dio48egpio->chip.set = dio48e_gpio_set;
  269. dio48egpio->base = base;
  270. dio48egpio->irq = irq;
  271. spin_lock_init(&dio48egpio->lock);
  272. dev_set_drvdata(dev, dio48egpio);
  273. err = gpiochip_add_data(&dio48egpio->chip, dio48egpio);
  274. if (err) {
  275. dev_err(dev, "GPIO registering failed (%d)\n", err);
  276. return err;
  277. }
  278. /* initialize all GPIO as output */
  279. outb(0x80, base + 3);
  280. outb(0x00, base);
  281. outb(0x00, base + 1);
  282. outb(0x00, base + 2);
  283. outb(0x00, base + 3);
  284. outb(0x80, base + 7);
  285. outb(0x00, base + 4);
  286. outb(0x00, base + 5);
  287. outb(0x00, base + 6);
  288. outb(0x00, base + 7);
  289. /* disable IRQ by default */
  290. inb(base + 0xB);
  291. err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0,
  292. handle_edge_irq, IRQ_TYPE_NONE);
  293. if (err) {
  294. dev_err(dev, "Could not add irqchip (%d)\n", err);
  295. goto err_gpiochip_remove;
  296. }
  297. err = request_irq(irq, dio48e_irq_handler, 0, name, dio48egpio);
  298. if (err) {
  299. dev_err(dev, "IRQ handler registering failed (%d)\n", err);
  300. goto err_gpiochip_remove;
  301. }
  302. return 0;
  303. err_gpiochip_remove:
  304. gpiochip_remove(&dio48egpio->chip);
  305. return err;
  306. }
  307. static int dio48e_remove(struct platform_device *pdev)
  308. {
  309. struct dio48e_gpio *const dio48egpio = platform_get_drvdata(pdev);
  310. free_irq(dio48egpio->irq, dio48egpio);
  311. gpiochip_remove(&dio48egpio->chip);
  312. return 0;
  313. }
  314. static struct platform_device *dio48e_device;
  315. static struct platform_driver dio48e_driver = {
  316. .driver = {
  317. .name = "104-dio-48e"
  318. },
  319. .remove = dio48e_remove
  320. };
  321. static void __exit dio48e_exit(void)
  322. {
  323. platform_device_unregister(dio48e_device);
  324. platform_driver_unregister(&dio48e_driver);
  325. }
  326. static int __init dio48e_init(void)
  327. {
  328. int err;
  329. dio48e_device = platform_device_alloc(dio48e_driver.driver.name, -1);
  330. if (!dio48e_device)
  331. return -ENOMEM;
  332. err = platform_device_add(dio48e_device);
  333. if (err)
  334. goto err_platform_device;
  335. err = platform_driver_probe(&dio48e_driver, dio48e_probe);
  336. if (err)
  337. goto err_platform_driver;
  338. return 0;
  339. err_platform_driver:
  340. platform_device_del(dio48e_device);
  341. err_platform_device:
  342. platform_device_put(dio48e_device);
  343. return err;
  344. }
  345. module_init(dio48e_init);
  346. module_exit(dio48e_exit);
  347. MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
  348. MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver");
  349. MODULE_LICENSE("GPL v2");