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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * GPIO driver for the ACCES 104-DIO-48E series
  4. * Copyright (C) 2016 William Breathitt Gray
  5. *
  6. * This driver supports the following ACCES devices: 104-DIO-48E and
  7. * 104-DIO-24E.
  8. */
  9. #include <linux/bits.h>
  10. #include <linux/device.h>
  11. #include <linux/err.h>
  12. #include <linux/i8254.h>
  13. #include <linux/ioport.h>
  14. #include <linux/irq.h>
  15. #include <linux/isa.h>
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/moduleparam.h>
  19. #include <linux/regmap.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/types.h>
  22. #include "gpio-i8255.h"
  23. MODULE_IMPORT_NS(I8255);
  24. #define DIO48E_EXTENT 16
  25. #define MAX_NUM_DIO48E max_num_isa_dev(DIO48E_EXTENT)
  26. static unsigned int base[MAX_NUM_DIO48E];
  27. static unsigned int num_dio48e;
  28. module_param_hw_array(base, uint, ioport, &num_dio48e, 0);
  29. MODULE_PARM_DESC(base, "ACCES 104-DIO-48E base addresses");
  30. static unsigned int irq[MAX_NUM_DIO48E];
  31. static unsigned int num_irq;
  32. module_param_hw_array(irq, uint, irq, &num_irq, 0);
  33. MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers");
  34. #define DIO48E_ENABLE_INTERRUPT 0xB
  35. #define DIO48E_DISABLE_INTERRUPT DIO48E_ENABLE_INTERRUPT
  36. #define DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING 0xD
  37. #define DIO48E_DISABLE_COUNTER_TIMER_ADDRESSING DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING
  38. #define DIO48E_CLEAR_INTERRUPT 0xF
  39. #define DIO48E_NUM_PPI 2
  40. static const struct regmap_range dio48e_wr_ranges[] = {
  41. regmap_reg_range(0x0, 0x9), regmap_reg_range(0xB, 0xB),
  42. regmap_reg_range(0xD, 0xD), regmap_reg_range(0xF, 0xF),
  43. };
  44. static const struct regmap_range dio48e_rd_ranges[] = {
  45. regmap_reg_range(0x0, 0x2), regmap_reg_range(0x4, 0x6),
  46. regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD),
  47. regmap_reg_range(0xF, 0xF),
  48. };
  49. static const struct regmap_range dio48e_volatile_ranges[] = {
  50. i8255_volatile_regmap_range(0x0), i8255_volatile_regmap_range(0x4),
  51. regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD),
  52. regmap_reg_range(0xF, 0xF),
  53. };
  54. static const struct regmap_range dio48e_precious_ranges[] = {
  55. regmap_reg_range(0xB, 0xB), regmap_reg_range(0xD, 0xD),
  56. regmap_reg_range(0xF, 0xF),
  57. };
  58. static const struct regmap_access_table dio48e_wr_table = {
  59. .yes_ranges = dio48e_wr_ranges,
  60. .n_yes_ranges = ARRAY_SIZE(dio48e_wr_ranges),
  61. };
  62. static const struct regmap_access_table dio48e_rd_table = {
  63. .yes_ranges = dio48e_rd_ranges,
  64. .n_yes_ranges = ARRAY_SIZE(dio48e_rd_ranges),
  65. };
  66. static const struct regmap_access_table dio48e_volatile_table = {
  67. .yes_ranges = dio48e_volatile_ranges,
  68. .n_yes_ranges = ARRAY_SIZE(dio48e_volatile_ranges),
  69. };
  70. static const struct regmap_access_table dio48e_precious_table = {
  71. .yes_ranges = dio48e_precious_ranges,
  72. .n_yes_ranges = ARRAY_SIZE(dio48e_precious_ranges),
  73. };
  74. static const struct regmap_range pit_wr_ranges[] = {
  75. regmap_reg_range(0x0, 0x3),
  76. };
  77. static const struct regmap_range pit_rd_ranges[] = {
  78. regmap_reg_range(0x0, 0x2),
  79. };
  80. static const struct regmap_access_table pit_wr_table = {
  81. .yes_ranges = pit_wr_ranges,
  82. .n_yes_ranges = ARRAY_SIZE(pit_wr_ranges),
  83. };
  84. static const struct regmap_access_table pit_rd_table = {
  85. .yes_ranges = pit_rd_ranges,
  86. .n_yes_ranges = ARRAY_SIZE(pit_rd_ranges),
  87. };
  88. /* only bit 3 on each respective Port C supports interrupts */
  89. #define DIO48E_REGMAP_IRQ(_ppi) \
  90. [19 + (_ppi) * 24] = { \
  91. .mask = BIT(_ppi), \
  92. .type = { .types_supported = IRQ_TYPE_EDGE_RISING }, \
  93. }
  94. static const struct regmap_irq dio48e_regmap_irqs[] = {
  95. DIO48E_REGMAP_IRQ(0), DIO48E_REGMAP_IRQ(1),
  96. };
  97. /**
  98. * struct dio48e_gpio - GPIO device private data structure
  99. * @lock: synchronization lock to prevent I/O race conditions
  100. * @map: Regmap for the device
  101. * @regs: virtual mapping for device registers
  102. * @flags: IRQ flags saved during locking
  103. * @irq_mask: Current IRQ mask state on the device
  104. */
  105. struct dio48e_gpio {
  106. raw_spinlock_t lock;
  107. struct regmap *map;
  108. void __iomem *regs;
  109. unsigned long flags;
  110. unsigned int irq_mask;
  111. };
  112. static void dio48e_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock)
  113. {
  114. struct dio48e_gpio *const dio48egpio = lock_arg;
  115. unsigned long flags;
  116. raw_spin_lock_irqsave(&dio48egpio->lock, flags);
  117. dio48egpio->flags = flags;
  118. }
  119. static void dio48e_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock)
  120. {
  121. struct dio48e_gpio *const dio48egpio = lock_arg;
  122. raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags);
  123. }
  124. static void pit_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock)
  125. {
  126. struct dio48e_gpio *const dio48egpio = lock_arg;
  127. unsigned long flags;
  128. raw_spin_lock_irqsave(&dio48egpio->lock, flags);
  129. dio48egpio->flags = flags;
  130. iowrite8(0x00, dio48egpio->regs + DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING);
  131. }
  132. static void pit_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock)
  133. {
  134. struct dio48e_gpio *const dio48egpio = lock_arg;
  135. ioread8(dio48egpio->regs + DIO48E_DISABLE_COUNTER_TIMER_ADDRESSING);
  136. raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags);
  137. }
  138. static int dio48e_handle_mask_sync(const int index,
  139. const unsigned int mask_buf_def,
  140. const unsigned int mask_buf,
  141. void *const irq_drv_data)
  142. {
  143. struct dio48e_gpio *const dio48egpio = irq_drv_data;
  144. const unsigned int prev_mask = dio48egpio->irq_mask;
  145. int err;
  146. unsigned int val;
  147. /* exit early if no change since the previous mask */
  148. if (mask_buf == prev_mask)
  149. return 0;
  150. /* remember the current mask for the next mask sync */
  151. dio48egpio->irq_mask = mask_buf;
  152. /* if all previously masked, enable interrupts when unmasking */
  153. if (prev_mask == mask_buf_def) {
  154. err = regmap_write(dio48egpio->map, DIO48E_CLEAR_INTERRUPT, 0x00);
  155. if (err)
  156. return err;
  157. return regmap_write(dio48egpio->map, DIO48E_ENABLE_INTERRUPT, 0x00);
  158. }
  159. /* if all are currently masked, disable interrupts */
  160. if (mask_buf == mask_buf_def)
  161. return regmap_read(dio48egpio->map, DIO48E_DISABLE_INTERRUPT, &val);
  162. return 0;
  163. }
  164. #define DIO48E_NGPIO 48
  165. static const char *dio48e_names[DIO48E_NGPIO] = {
  166. "PPI Group 0 Port A 0", "PPI Group 0 Port A 1", "PPI Group 0 Port A 2",
  167. "PPI Group 0 Port A 3", "PPI Group 0 Port A 4", "PPI Group 0 Port A 5",
  168. "PPI Group 0 Port A 6", "PPI Group 0 Port A 7", "PPI Group 0 Port B 0",
  169. "PPI Group 0 Port B 1", "PPI Group 0 Port B 2", "PPI Group 0 Port B 3",
  170. "PPI Group 0 Port B 4", "PPI Group 0 Port B 5", "PPI Group 0 Port B 6",
  171. "PPI Group 0 Port B 7", "PPI Group 0 Port C 0", "PPI Group 0 Port C 1",
  172. "PPI Group 0 Port C 2", "PPI Group 0 Port C 3", "PPI Group 0 Port C 4",
  173. "PPI Group 0 Port C 5", "PPI Group 0 Port C 6", "PPI Group 0 Port C 7",
  174. "PPI Group 1 Port A 0", "PPI Group 1 Port A 1", "PPI Group 1 Port A 2",
  175. "PPI Group 1 Port A 3", "PPI Group 1 Port A 4", "PPI Group 1 Port A 5",
  176. "PPI Group 1 Port A 6", "PPI Group 1 Port A 7", "PPI Group 1 Port B 0",
  177. "PPI Group 1 Port B 1", "PPI Group 1 Port B 2", "PPI Group 1 Port B 3",
  178. "PPI Group 1 Port B 4", "PPI Group 1 Port B 5", "PPI Group 1 Port B 6",
  179. "PPI Group 1 Port B 7", "PPI Group 1 Port C 0", "PPI Group 1 Port C 1",
  180. "PPI Group 1 Port C 2", "PPI Group 1 Port C 3", "PPI Group 1 Port C 4",
  181. "PPI Group 1 Port C 5", "PPI Group 1 Port C 6", "PPI Group 1 Port C 7"
  182. };
  183. static int dio48e_irq_init_hw(struct regmap *const map)
  184. {
  185. unsigned int val;
  186. /* Disable IRQ by default */
  187. return regmap_read(map, DIO48E_DISABLE_INTERRUPT, &val);
  188. }
  189. static int dio48e_probe(struct device *dev, unsigned int id)
  190. {
  191. const char *const name = dev_name(dev);
  192. struct i8255_regmap_config config = {};
  193. void __iomem *regs;
  194. struct regmap *map;
  195. struct regmap_config dio48e_regmap_config;
  196. struct regmap_config pit_regmap_config;
  197. struct i8254_regmap_config pit_config;
  198. int err;
  199. struct regmap_irq_chip *chip;
  200. struct dio48e_gpio *dio48egpio;
  201. struct regmap_irq_chip_data *chip_data;
  202. if (!devm_request_region(dev, base[id], DIO48E_EXTENT, name)) {
  203. dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
  204. base[id], base[id] + DIO48E_EXTENT);
  205. return -EBUSY;
  206. }
  207. dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL);
  208. if (!dio48egpio)
  209. return -ENOMEM;
  210. regs = devm_ioport_map(dev, base[id], DIO48E_EXTENT);
  211. if (!regs)
  212. return -ENOMEM;
  213. dio48egpio->regs = regs;
  214. raw_spin_lock_init(&dio48egpio->lock);
  215. dio48e_regmap_config = (struct regmap_config) {
  216. .reg_bits = 8,
  217. .reg_stride = 1,
  218. .val_bits = 8,
  219. .lock = dio48e_regmap_lock,
  220. .unlock = dio48e_regmap_unlock,
  221. .lock_arg = dio48egpio,
  222. .io_port = true,
  223. .wr_table = &dio48e_wr_table,
  224. .rd_table = &dio48e_rd_table,
  225. .volatile_table = &dio48e_volatile_table,
  226. .precious_table = &dio48e_precious_table,
  227. .cache_type = REGCACHE_FLAT,
  228. };
  229. map = devm_regmap_init_mmio(dev, regs, &dio48e_regmap_config);
  230. if (IS_ERR(map))
  231. return dev_err_probe(dev, PTR_ERR(map),
  232. "Unable to initialize register map\n");
  233. dio48egpio->map = map;
  234. pit_regmap_config = (struct regmap_config) {
  235. .name = "i8254",
  236. .reg_bits = 8,
  237. .reg_stride = 1,
  238. .val_bits = 8,
  239. .lock = pit_regmap_lock,
  240. .unlock = pit_regmap_unlock,
  241. .lock_arg = dio48egpio,
  242. .io_port = true,
  243. .wr_table = &pit_wr_table,
  244. .rd_table = &pit_rd_table,
  245. };
  246. pit_config.map = devm_regmap_init_mmio(dev, regs, &pit_regmap_config);
  247. if (IS_ERR(pit_config.map))
  248. return dev_err_probe(dev, PTR_ERR(pit_config.map),
  249. "Unable to initialize i8254 register map\n");
  250. chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
  251. if (!chip)
  252. return -ENOMEM;
  253. chip->name = name;
  254. chip->mask_base = DIO48E_ENABLE_INTERRUPT;
  255. chip->ack_base = DIO48E_CLEAR_INTERRUPT;
  256. chip->no_status = true;
  257. chip->num_regs = 1;
  258. chip->irqs = dio48e_regmap_irqs;
  259. chip->num_irqs = ARRAY_SIZE(dio48e_regmap_irqs);
  260. chip->handle_mask_sync = dio48e_handle_mask_sync;
  261. chip->irq_drv_data = dio48egpio;
  262. /* Initialize to prevent spurious interrupts before we're ready */
  263. err = dio48e_irq_init_hw(map);
  264. if (err)
  265. return err;
  266. err = devm_regmap_add_irq_chip(dev, map, irq[id], 0, 0, chip, &chip_data);
  267. if (err)
  268. return dev_err_probe(dev, err, "IRQ registration failed\n");
  269. pit_config.parent = dev;
  270. err = devm_i8254_regmap_register(dev, &pit_config);
  271. if (err)
  272. return err;
  273. config.parent = dev;
  274. config.map = map;
  275. config.num_ppi = DIO48E_NUM_PPI;
  276. config.names = dio48e_names;
  277. config.domain = regmap_irq_get_domain(chip_data);
  278. return devm_i8255_regmap_register(dev, &config);
  279. }
  280. static struct isa_driver dio48e_driver = {
  281. .probe = dio48e_probe,
  282. .driver = {
  283. .name = "104-dio-48e"
  284. },
  285. };
  286. module_isa_driver_with_irq(dio48e_driver, num_dio48e, num_irq);
  287. MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
  288. MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver");
  289. MODULE_LICENSE("GPL v2");
  290. MODULE_IMPORT_NS(I8254);