gpio-janz-ttl.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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 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 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 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 = dev_get_platdata(&pdev->dev);
  127. if (!pdata) {
  128. dev_err(dev, "no platform data\n");
  129. return -ENXIO;
  130. }
  131. mod = devm_kzalloc(dev, sizeof(*mod), GFP_KERNEL);
  132. if (!mod)
  133. return -ENOMEM;
  134. platform_set_drvdata(pdev, mod);
  135. spin_lock_init(&mod->lock);
  136. /* get access to the MODULbus registers for this module */
  137. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  138. mod->regs = devm_ioremap_resource(dev, res);
  139. if (IS_ERR(mod->regs))
  140. return PTR_ERR(mod->regs);
  141. ttl_setup_device(mod);
  142. /* Initialize the GPIO data structures */
  143. gpio = &mod->gpio;
  144. gpio->dev = &pdev->dev;
  145. gpio->label = pdev->name;
  146. gpio->get = ttl_get_value;
  147. gpio->set = ttl_set_value;
  148. gpio->owner = THIS_MODULE;
  149. /* request dynamic allocation */
  150. gpio->base = -1;
  151. gpio->ngpio = 20;
  152. ret = gpiochip_add(gpio);
  153. if (ret) {
  154. dev_err(dev, "unable to add GPIO chip\n");
  155. return ret;
  156. }
  157. return 0;
  158. }
  159. static int ttl_remove(struct platform_device *pdev)
  160. {
  161. struct ttl_module *mod = platform_get_drvdata(pdev);
  162. gpiochip_remove(&mod->gpio);
  163. return 0;
  164. }
  165. static struct platform_driver ttl_driver = {
  166. .driver = {
  167. .name = DRV_NAME,
  168. },
  169. .probe = ttl_probe,
  170. .remove = ttl_remove,
  171. };
  172. module_platform_driver(ttl_driver);
  173. MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
  174. MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
  175. MODULE_LICENSE("GPL");
  176. MODULE_ALIAS("platform:janz-ttl");