pwmtest.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * arkmicro pwmtest driver
  3. *
  4. * Licensed under GPLv2 or later.
  5. */
  6. #include <linux/module.h>
  7. #include <linux/platform_device.h>
  8. #include <linux/gpio/consumer.h>
  9. #include <linux/of.h>
  10. #include <linux/clk.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/io.h>
  13. #include <linux/err.h>
  14. #include <linux/miscdevice.h>
  15. #include <linux/fs.h>
  16. #include <linux/uaccess.h>
  17. #include <linux/sched.h>
  18. #define PWM_MAX_NUM 4
  19. #define PWMTEST_IOCTL_BASE 0x9F
  20. #define PWMTEST_IOCTL_GET_PWM0_COUNT _IOR(PWMTEST_IOCTL_BASE, 0, int)
  21. #define PWMTEST_IOCTL_GET_PWM1_COUNT _IOR(PWMTEST_IOCTL_BASE, 1, int)
  22. #define PWMTEST_IOCTL_GET_PWM2_COUNT _IOR(PWMTEST_IOCTL_BASE, 2, int)
  23. #define PWMTEST_IOCTL_GET_PWM3_COUNT _IOR(PWMTEST_IOCTL_BASE, 3, int)
  24. struct ark_pwmtest {
  25. int irqs[PWM_MAX_NUM];
  26. struct gpio_desc *gpios[PWM_MAX_NUM];
  27. unsigned int pwmcount[PWM_MAX_NUM];
  28. int debounce_detect;
  29. };
  30. static struct ark_pwmtest *g_pwmtest = NULL;
  31. static int pwmtest_misc_open(struct inode *inode, struct file *filp)
  32. {
  33. filp->private_data = g_pwmtest;
  34. return 0;
  35. }
  36. static int pwmtest_misc_release(struct inode *inode, struct file *filp)
  37. {
  38. return 0;
  39. }
  40. static long pwmtest_misc_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
  41. {
  42. struct ark_pwmtest *pwmtest = (struct ark_pwmtest *)filp->private_data;
  43. int error = 0;
  44. switch (cmd) {
  45. case PWMTEST_IOCTL_GET_PWM0_COUNT:
  46. if (copy_to_user((void*)arg, &pwmtest->pwmcount[0], sizeof(pwmtest->pwmcount[0]))) {
  47. printk("%s %d: copy_to_user error\n", __FUNCTION__, __LINE__);
  48. error = -EFAULT;
  49. }
  50. break;
  51. case PWMTEST_IOCTL_GET_PWM1_COUNT:
  52. if (copy_to_user((void*)arg, &pwmtest->pwmcount[1], sizeof(pwmtest->pwmcount[1]))) {
  53. printk("%s %d: copy_to_user error\n", __FUNCTION__, __LINE__);
  54. error = -EFAULT;
  55. }
  56. break;
  57. case PWMTEST_IOCTL_GET_PWM2_COUNT:
  58. if (copy_to_user((void*)arg, &pwmtest->pwmcount[2], sizeof(pwmtest->pwmcount[2]))) {
  59. printk("%s %d: copy_to_user error\n", __FUNCTION__, __LINE__);
  60. error = -EFAULT;
  61. }
  62. break;
  63. case PWMTEST_IOCTL_GET_PWM3_COUNT:
  64. if (copy_to_user((void*)arg, &pwmtest->pwmcount[3], sizeof(pwmtest->pwmcount[3]))) {
  65. printk("%s %d: copy_to_user error\n", __FUNCTION__, __LINE__);
  66. error = -EFAULT;
  67. }
  68. break;
  69. default:
  70. printk("%s %d: undefined cmd (0x%2X)\n", __FUNCTION__, __LINE__, cmd);
  71. error = -EINVAL;
  72. }
  73. return error;
  74. }
  75. const struct file_operations pwmtest_misc_fops = {
  76. .owner = THIS_MODULE,
  77. .llseek = no_llseek,
  78. .open = pwmtest_misc_open,
  79. .release = pwmtest_misc_release,
  80. .unlocked_ioctl = pwmtest_misc_ioctl,
  81. };
  82. static struct miscdevice pwmtest_misc_device = {
  83. MISC_DYNAMIC_MINOR,
  84. "pwmtest",
  85. &pwmtest_misc_fops
  86. };
  87. static irqreturn_t pwmtest_interrupt(int irq, void *dev_id)
  88. {
  89. unsigned int *pwmcount = (unsigned int*)dev_id;
  90. *pwmcount = *pwmcount + 1;
  91. return IRQ_HANDLED;
  92. }
  93. static int ark_pwmtest_probe(struct platform_device *pdev)
  94. {
  95. struct ark_pwmtest *pwmtest;
  96. int err;
  97. int i;
  98. pwmtest = devm_kzalloc(&pdev->dev, sizeof(*pwmtest), GFP_KERNEL);
  99. if (!pwmtest)
  100. return -ENOMEM;
  101. if (of_property_read_u32(pdev->dev.of_node, "debounce-detect", &pwmtest->debounce_detect)) {
  102. pwmtest->debounce_detect = 20;
  103. }
  104. for (i = 1; i < PWM_MAX_NUM; i++) {
  105. pwmtest->gpios[i] = devm_gpiod_get_index(&pdev->dev, "pwm", i - 1, GPIOD_IN);
  106. if (IS_ERR(pwmtest->gpios[i]))
  107. return PTR_ERR(pwmtest->gpios[i]);
  108. gpiod_set_debounce(pwmtest->gpios[i], pwmtest->debounce_detect);
  109. pwmtest->irqs[i] = platform_get_irq(pdev, i - 1);
  110. if (pwmtest->irqs[i] < 0)
  111. return pwmtest->irqs[i];
  112. err = devm_request_irq(&pdev->dev, pwmtest->irqs[i], pwmtest_interrupt, 0, "ark-pwmtest", &pwmtest->pwmcount[i]);
  113. if (err){
  114. printk(KERN_ERR "%s %d: can't get assigned pwmtest irq %d, error %d\n",
  115. __FUNCTION__, __LINE__, pwmtest->irqs[i], err);
  116. return err;
  117. }
  118. }
  119. /* Register the miscdevice */
  120. err = misc_register(&pwmtest_misc_device);
  121. if (err) {
  122. dev_err(&pdev->dev, "unable to register miscdevice\n");
  123. return err;
  124. }
  125. g_pwmtest = pwmtest;
  126. return 0;
  127. }
  128. static int ark_pwmtest_remove(struct platform_device *pdev)
  129. {
  130. misc_deregister(&pwmtest_misc_device);
  131. return 0;
  132. }
  133. static const struct of_device_id ark_pwmtest_of_match[] = {
  134. { .compatible = "arkmicro,ark-pwmtest", },
  135. { /* sentinel */ }
  136. };
  137. static struct platform_driver vdec_of_driver = {
  138. .driver = {
  139. .name = "ark-pwmtest",
  140. .owner = THIS_MODULE,
  141. .of_match_table = of_match_ptr(ark_pwmtest_of_match),
  142. },
  143. .probe = ark_pwmtest_probe,
  144. .remove = ark_pwmtest_remove,
  145. };
  146. module_platform_driver(vdec_of_driver);