gio.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * arch/sh/boards/landisk/gio.c - driver for landisk
  4. *
  5. * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
  6. * LANDISK and USL-5P Button, LED and GIO driver drive function.
  7. *
  8. * Copylight (C) 2006 kogiidena
  9. * Copylight (C) 2002 Atom Create Engineering Co., Ltd. *
  10. */
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/kdev_t.h>
  14. #include <linux/cdev.h>
  15. #include <linux/fs.h>
  16. #include <asm/io.h>
  17. #include <linux/uaccess.h>
  18. #include <mach-landisk/mach/gio.h>
  19. #include <mach-landisk/mach/iodata_landisk.h>
  20. #define DEVCOUNT 4
  21. #define GIO_MINOR 2 /* GIO minor no. */
  22. static dev_t dev;
  23. static struct cdev *cdev_p;
  24. static int openCnt;
  25. static int gio_open(struct inode *inode, struct file *filp)
  26. {
  27. int minor = iminor(inode);
  28. int ret = -ENOENT;
  29. preempt_disable();
  30. if (minor < DEVCOUNT) {
  31. if (openCnt > 0) {
  32. ret = -EALREADY;
  33. } else {
  34. openCnt++;
  35. ret = 0;
  36. }
  37. }
  38. preempt_enable();
  39. return ret;
  40. }
  41. static int gio_close(struct inode *inode, struct file *filp)
  42. {
  43. int minor = iminor(inode);
  44. if (minor < DEVCOUNT) {
  45. openCnt--;
  46. }
  47. return 0;
  48. }
  49. static long gio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  50. {
  51. unsigned int data;
  52. static unsigned int addr = 0;
  53. if (cmd & 0x01) { /* write */
  54. if (copy_from_user(&data, (int *)arg, sizeof(int))) {
  55. return -EFAULT;
  56. }
  57. }
  58. switch (cmd) {
  59. case GIODRV_IOCSGIOSETADDR: /* address set */
  60. addr = data;
  61. break;
  62. case GIODRV_IOCSGIODATA1: /* write byte */
  63. __raw_writeb((unsigned char)(0x0ff & data), addr);
  64. break;
  65. case GIODRV_IOCSGIODATA2: /* write word */
  66. if (addr & 0x01) {
  67. return -EFAULT;
  68. }
  69. __raw_writew((unsigned short int)(0x0ffff & data), addr);
  70. break;
  71. case GIODRV_IOCSGIODATA4: /* write long */
  72. if (addr & 0x03) {
  73. return -EFAULT;
  74. }
  75. __raw_writel(data, addr);
  76. break;
  77. case GIODRV_IOCGGIODATA1: /* read byte */
  78. data = __raw_readb(addr);
  79. break;
  80. case GIODRV_IOCGGIODATA2: /* read word */
  81. if (addr & 0x01) {
  82. return -EFAULT;
  83. }
  84. data = __raw_readw(addr);
  85. break;
  86. case GIODRV_IOCGGIODATA4: /* read long */
  87. if (addr & 0x03) {
  88. return -EFAULT;
  89. }
  90. data = __raw_readl(addr);
  91. break;
  92. default:
  93. return -EFAULT;
  94. break;
  95. }
  96. if ((cmd & 0x01) == 0) { /* read */
  97. if (copy_to_user((int *)arg, &data, sizeof(int))) {
  98. return -EFAULT;
  99. }
  100. }
  101. return 0;
  102. }
  103. static const struct file_operations gio_fops = {
  104. .owner = THIS_MODULE,
  105. .open = gio_open, /* open */
  106. .release = gio_close, /* release */
  107. .unlocked_ioctl = gio_ioctl,
  108. .llseek = noop_llseek,
  109. };
  110. static int __init gio_init(void)
  111. {
  112. int error;
  113. printk(KERN_INFO "gio: driver initialized\n");
  114. openCnt = 0;
  115. if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "gio")) < 0) {
  116. printk(KERN_ERR
  117. "gio: Couldn't alloc_chrdev_region, error=%d\n",
  118. error);
  119. return 1;
  120. }
  121. cdev_p = cdev_alloc();
  122. cdev_p->ops = &gio_fops;
  123. error = cdev_add(cdev_p, dev, DEVCOUNT);
  124. if (error) {
  125. printk(KERN_ERR
  126. "gio: Couldn't cdev_add, error=%d\n", error);
  127. return 1;
  128. }
  129. return 0;
  130. }
  131. static void __exit gio_exit(void)
  132. {
  133. cdev_del(cdev_p);
  134. unregister_chrdev_region(dev, DEVCOUNT);
  135. }
  136. module_init(gio_init);
  137. module_exit(gio_exit);
  138. MODULE_LICENSE("GPL");