janz-ttl.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. * Janz MODULbus VMOD-TTL GPIO Driver
  3. *
  4. * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2 of the License, or (at your
  9. * option) any later version.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/init.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/delay.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/io.h>
  18. #include <linux/gpio.h>
  19. #include <linux/slab.h>
  20. #include <linux/mfd/janz.h>
  21. #define DRV_NAME "janz-ttl"
  22. #define PORTA_DIRECTION 0x23
  23. #define PORTB_DIRECTION 0x2B
  24. #define PORTC_DIRECTION 0x06
  25. #define PORTA_IOCTL 0x24
  26. #define PORTB_IOCTL 0x2C
  27. #define PORTC_IOCTL 0x07
  28. #define MASTER_INT_CTL 0x00
  29. #define MASTER_CONF_CTL 0x01
  30. #define CONF_PAE (1 << 2)
  31. #define CONF_PBE (1 << 7)
  32. #define CONF_PCE (1 << 4)
  33. struct ttl_control_regs {
  34. __be16 portc;
  35. __be16 portb;
  36. __be16 porta;
  37. __be16 control;
  38. };
  39. struct ttl_module {
  40. struct gpio_chip gpio;
  41. /* base address of registers */
  42. struct ttl_control_regs __iomem *regs;
  43. u8 portc_shadow;
  44. u8 portb_shadow;
  45. u8 porta_shadow;
  46. spinlock_t lock;
  47. };
  48. static int ttl_get_value(struct gpio_chip *gpio, unsigned offset)
  49. {
  50. struct ttl_module *mod = dev_get_drvdata(gpio->dev);
  51. u8 *shadow;
  52. int ret;
  53. if (offset < 8) {
  54. shadow = &mod->porta_shadow;
  55. } else if (offset < 16) {
  56. shadow = &mod->portb_shadow;
  57. offset -= 8;
  58. } else {
  59. shadow = &mod->portc_shadow;
  60. offset -= 16;
  61. }
  62. spin_lock(&mod->lock);
  63. ret = *shadow & (1 << offset);
  64. spin_unlock(&mod->lock);
  65. return ret;
  66. }
  67. static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value)
  68. {
  69. struct ttl_module *mod = dev_get_drvdata(gpio->dev);
  70. void __iomem *port;
  71. u8 *shadow;
  72. if (offset < 8) {
  73. port = &mod->regs->porta;
  74. shadow = &mod->porta_shadow;
  75. } else if (offset < 16) {
  76. port = &mod->regs->portb;
  77. shadow = &mod->portb_shadow;
  78. offset -= 8;
  79. } else {
  80. port = &mod->regs->portc;
  81. shadow = &mod->portc_shadow;
  82. offset -= 16;
  83. }
  84. spin_lock(&mod->lock);
  85. if (value)
  86. *shadow |= (1 << offset);
  87. else
  88. *shadow &= ~(1 << offset);
  89. iowrite16be(*shadow, port);
  90. spin_unlock(&mod->lock);
  91. }
  92. static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val)
  93. {
  94. iowrite16be(reg, &mod->regs->control);
  95. iowrite16be(val, &mod->regs->control);
  96. }
  97. static void __devinit ttl_setup_device(struct ttl_module *mod)
  98. {
  99. /* reset the device to a known state */
  100. iowrite16be(0x0000, &mod->regs->control);
  101. iowrite16be(0x0001, &mod->regs->control);
  102. iowrite16be(0x0000, &mod->regs->control);
  103. /* put all ports in open-drain mode */
  104. ttl_write_reg(mod, PORTA_IOCTL, 0x00ff);
  105. ttl_write_reg(mod, PORTB_IOCTL, 0x00ff);
  106. ttl_write_reg(mod, PORTC_IOCTL, 0x000f);
  107. /* set all ports as outputs */
  108. ttl_write_reg(mod, PORTA_DIRECTION, 0x0000);
  109. ttl_write_reg(mod, PORTB_DIRECTION, 0x0000);
  110. ttl_write_reg(mod, PORTC_DIRECTION, 0x0000);
  111. /* set all ports to drive zeroes */
  112. iowrite16be(0x0000, &mod->regs->porta);
  113. iowrite16be(0x0000, &mod->regs->portb);
  114. iowrite16be(0x0000, &mod->regs->portc);
  115. /* enable all ports */
  116. ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE);
  117. }
  118. static int __devinit ttl_probe(struct platform_device *pdev)
  119. {
  120. struct janz_platform_data *pdata;
  121. struct device *dev = &pdev->dev;
  122. struct ttl_module *mod;
  123. struct gpio_chip *gpio;
  124. struct resource *res;
  125. int ret;
  126. pdata = pdev->dev.platform_data;
  127. if (!pdata) {
  128. dev_err(dev, "no platform data\n");
  129. ret = -ENXIO;
  130. goto out_return;
  131. }
  132. mod = kzalloc(sizeof(*mod), GFP_KERNEL);
  133. if (!mod) {
  134. dev_err(dev, "unable to allocate private data\n");
  135. ret = -ENOMEM;
  136. goto out_return;
  137. }
  138. platform_set_drvdata(pdev, mod);
  139. spin_lock_init(&mod->lock);
  140. /* get access to the MODULbus registers for this module */
  141. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  142. if (!res) {
  143. dev_err(dev, "MODULbus registers not found\n");
  144. ret = -ENODEV;
  145. goto out_free_mod;
  146. }
  147. mod->regs = ioremap(res->start, resource_size(res));
  148. if (!mod->regs) {
  149. dev_err(dev, "MODULbus registers not ioremap\n");
  150. ret = -ENOMEM;
  151. goto out_free_mod;
  152. }
  153. ttl_setup_device(mod);
  154. /* Initialize the GPIO data structures */
  155. gpio = &mod->gpio;
  156. gpio->dev = &pdev->dev;
  157. gpio->label = pdev->name;
  158. gpio->get = ttl_get_value;
  159. gpio->set = ttl_set_value;
  160. gpio->owner = THIS_MODULE;
  161. /* request dynamic allocation */
  162. gpio->base = -1;
  163. gpio->ngpio = 20;
  164. ret = gpiochip_add(gpio);
  165. if (ret) {
  166. dev_err(dev, "unable to add GPIO chip\n");
  167. goto out_iounmap_regs;
  168. }
  169. dev_info(&pdev->dev, "module %d: registered GPIO device\n",
  170. pdata->modno);
  171. return 0;
  172. out_iounmap_regs:
  173. iounmap(mod->regs);
  174. out_free_mod:
  175. kfree(mod);
  176. out_return:
  177. return ret;
  178. }
  179. static int __devexit ttl_remove(struct platform_device *pdev)
  180. {
  181. struct ttl_module *mod = platform_get_drvdata(pdev);
  182. struct device *dev = &pdev->dev;
  183. int ret;
  184. ret = gpiochip_remove(&mod->gpio);
  185. if (ret) {
  186. dev_err(dev, "unable to remove GPIO chip\n");
  187. return ret;
  188. }
  189. iounmap(mod->regs);
  190. kfree(mod);
  191. return 0;
  192. }
  193. static struct platform_driver ttl_driver = {
  194. .driver = {
  195. .name = DRV_NAME,
  196. .owner = THIS_MODULE,
  197. },
  198. .probe = ttl_probe,
  199. .remove = __devexit_p(ttl_remove),
  200. };
  201. static int __init ttl_init(void)
  202. {
  203. return platform_driver_register(&ttl_driver);
  204. }
  205. static void __exit ttl_exit(void)
  206. {
  207. platform_driver_unregister(&ttl_driver);
  208. }
  209. MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
  210. MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
  211. MODULE_LICENSE("GPL");
  212. MODULE_ALIAS("platform:janz-ttl");
  213. module_init(ttl_init);
  214. module_exit(ttl_exit);