pwm.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * Blackfin Pulse Width Modulation (PWM) core
  3. *
  4. * Copyright (c) 2011 Analog Devices Inc.
  5. *
  6. * Licensed under the GPL-2 or later.
  7. */
  8. #include <linux/module.h>
  9. #include <linux/pwm.h>
  10. #include <linux/slab.h>
  11. #include <asm/gptimers.h>
  12. #include <asm/portmux.h>
  13. struct pwm_device {
  14. unsigned id;
  15. unsigned short pin;
  16. };
  17. static const unsigned short pwm_to_gptimer_per[] = {
  18. P_TMR0, P_TMR1, P_TMR2, P_TMR3, P_TMR4, P_TMR5,
  19. P_TMR6, P_TMR7, P_TMR8, P_TMR9, P_TMR10, P_TMR11,
  20. };
  21. struct pwm_device *pwm_request(int pwm_id, const char *label)
  22. {
  23. struct pwm_device *pwm;
  24. int ret;
  25. /* XXX: pwm_id really should be unsigned */
  26. if (pwm_id < 0)
  27. return NULL;
  28. pwm = kzalloc(sizeof(*pwm), GFP_KERNEL);
  29. if (!pwm)
  30. return pwm;
  31. pwm->id = pwm_id;
  32. if (pwm->id >= ARRAY_SIZE(pwm_to_gptimer_per))
  33. goto err;
  34. pwm->pin = pwm_to_gptimer_per[pwm->id];
  35. ret = peripheral_request(pwm->pin, label);
  36. if (ret)
  37. goto err;
  38. return pwm;
  39. err:
  40. kfree(pwm);
  41. return NULL;
  42. }
  43. EXPORT_SYMBOL(pwm_request);
  44. void pwm_free(struct pwm_device *pwm)
  45. {
  46. peripheral_free(pwm->pin);
  47. kfree(pwm);
  48. }
  49. EXPORT_SYMBOL(pwm_free);
  50. int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
  51. {
  52. unsigned long period, duty;
  53. unsigned long long val;
  54. if (duty_ns < 0 || duty_ns > period_ns)
  55. return -EINVAL;
  56. val = (unsigned long long)get_sclk() * period_ns;
  57. do_div(val, NSEC_PER_SEC);
  58. period = val;
  59. val = (unsigned long long)period * duty_ns;
  60. do_div(val, period_ns);
  61. duty = period - val;
  62. if (duty >= period)
  63. duty = period - 1;
  64. set_gptimer_config(pwm->id, TIMER_MODE_PWM | TIMER_PERIOD_CNT);
  65. set_gptimer_pwidth(pwm->id, duty);
  66. set_gptimer_period(pwm->id, period);
  67. return 0;
  68. }
  69. EXPORT_SYMBOL(pwm_config);
  70. int pwm_enable(struct pwm_device *pwm)
  71. {
  72. enable_gptimer(pwm->id);
  73. return 0;
  74. }
  75. EXPORT_SYMBOL(pwm_enable);
  76. void pwm_disable(struct pwm_device *pwm)
  77. {
  78. disable_gptimer(pwm->id);
  79. }
  80. EXPORT_SYMBOL(pwm_disable);