gpio_dev.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * character device wrapper for generic gpio layer
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
  17. *
  18. * Feedback, Bugs... [email protected]
  19. *
  20. * dpg 20100106
  21. */
  22. #include <linux/module.h>
  23. #include <linux/errno.h>
  24. #include <linux/init.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/io.h>
  27. #include <asm/gpio.h>
  28. #include <asm/atomic.h>
  29. #include <linux/init.h>
  30. #include <linux/genhd.h>
  31. #include <linux/device.h>
  32. #include <linux/platform_device.h>
  33. #include <linux/gpio_dev.h>
  34. #include <linux/fs.h>
  35. #define DRVNAME "gpiodev"
  36. #define DEVNAME "gpio"
  37. static int dev_major;
  38. static struct class *gpiodev_class;
  39. /* third argument of user space ioctl ('arg' here) contains the <pin> */
  40. static int
  41. gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  42. {
  43. int retval = 0;
  44. switch (cmd)
  45. {
  46. case GPIO_GET:
  47. retval = gpio_get_value(arg);
  48. break;
  49. case GPIO_SET:
  50. gpio_set_value(arg, 1);
  51. break;
  52. case GPIO_CLEAR:
  53. gpio_set_value(arg, 0);
  54. break;
  55. case GPIO_DIR_IN:
  56. retval = gpio_direction_input(arg);
  57. break;
  58. case GPIO_DIR_OUT:
  59. retval = gpio_direction_output(arg, 0);
  60. break;
  61. case GPIO_DIR_HIGH:
  62. retval = gpio_direction_output(arg, 1);
  63. break;
  64. case GPIO_REQUEST:
  65. /* should be first ioctl operation on <pin> */
  66. retval = gpio_request(arg, DRVNAME);
  67. break;
  68. case GPIO_FREE:
  69. /* should be last ioctl operation on <pin> */
  70. /* may be needed first if previous user missed this ioctl */
  71. gpio_free(arg);
  72. break;
  73. case GPIO_CAN_SLEEP:
  74. retval = gpio_cansleep(arg);
  75. break;
  76. default:
  77. retval = -EINVAL;
  78. /* = -ENOTTY; // correct return but ... */
  79. break;
  80. }
  81. return retval;
  82. }
  83. /* Allow co-incident opens */
  84. static int
  85. gpio_open(struct inode *inode, struct file *file)
  86. {
  87. int result = 0;
  88. unsigned int dev_minor = MINOR(inode->i_rdev);
  89. if (dev_minor != 0)
  90. {
  91. printk(KERN_ERR DRVNAME ": trying to access unknown minor device -> %d\n", dev_minor);
  92. result = -ENODEV;
  93. goto out;
  94. }
  95. out:
  96. return result;
  97. }
  98. static int
  99. gpio_close(struct inode * inode, struct file * file)
  100. {
  101. /* could track all <pin>s requested by this fd and gpio_free()
  102. * them here
  103. */
  104. return 0;
  105. }
  106. struct file_operations gpio_fops = {
  107. unlocked_ioctl: gpio_ioctl,
  108. open: gpio_open,
  109. release: gpio_close
  110. };
  111. static int
  112. gpio_probe(struct platform_device *dev)
  113. {
  114. int result = 0;
  115. dev_major = register_chrdev(0, DEVNAME, &gpio_fops);
  116. if (!dev_major)
  117. {
  118. printk(KERN_ERR DRVNAME ": Error whilst opening %s \n", DEVNAME);
  119. result = -ENODEV;
  120. goto out;
  121. }
  122. gpiodev_class = class_create(THIS_MODULE, DRVNAME);
  123. device_create(gpiodev_class, NULL, MKDEV(dev_major, 0), dev, DEVNAME);
  124. printk(KERN_INFO DRVNAME ": gpio device registered with major %d\n", dev_major);
  125. out:
  126. return result;
  127. }
  128. static int
  129. gpio_remove(struct platform_device *dev)
  130. {
  131. unregister_chrdev(dev_major, DEVNAME);
  132. return 0;
  133. }
  134. static struct
  135. platform_driver gpio_driver = {
  136. .probe = gpio_probe,
  137. .remove = gpio_remove,
  138. .driver = {
  139. .name = "GPIODEV",
  140. .owner = THIS_MODULE,
  141. },
  142. };
  143. static int __init
  144. gpio_mod_init(void)
  145. {
  146. int ret = platform_driver_register(&gpio_driver);
  147. if (ret)
  148. printk(KERN_INFO DRVNAME ": Error registering platfom driver!\n");
  149. return ret;
  150. }
  151. static void __exit
  152. gpio_mod_exit(void)
  153. {
  154. platform_driver_unregister(&gpio_driver);
  155. }
  156. module_init (gpio_mod_init);
  157. module_exit (gpio_mod_exit);
  158. MODULE_LICENSE("GPL");
  159. MODULE_AUTHOR("John Crispin / OpenWrt +");
  160. MODULE_DESCRIPTION("Character device for for generic gpio api");