pwm-imx-util.c 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /*
  2. * (C) Copyright 2014
  3. * Heiko Schocher, DENX Software Engineering, hs@denx.de.
  4. *
  5. * Basic support for the pwm modul on imx6.
  6. *
  7. * Based on linux:drivers/pwm/pwm-imx.c
  8. * from
  9. * Sascha Hauer <s.hauer@pengutronix.de>
  10. *
  11. * SPDX-License-Identifier: GPL-2.0
  12. */
  13. #include <common.h>
  14. #include <div64.h>
  15. #include <asm/arch/imx-regs.h>
  16. /* pwm_id from 0..3 */
  17. struct pwm_regs *pwm_id_to_reg(int pwm_id)
  18. {
  19. switch (pwm_id) {
  20. case 0:
  21. return (struct pwm_regs *)PWM1_BASE_ADDR;
  22. case 1:
  23. return (struct pwm_regs *)PWM2_BASE_ADDR;
  24. case 2:
  25. return (struct pwm_regs *)PWM3_BASE_ADDR;
  26. case 3:
  27. return (struct pwm_regs *)PWM4_BASE_ADDR;
  28. default:
  29. printf("unknown pwm_id: %d\n", pwm_id);
  30. break;
  31. }
  32. return NULL;
  33. }
  34. int pwm_imx_get_parms(int period_ns, int duty_ns, unsigned long *period_c,
  35. unsigned long *duty_c, unsigned long *prescale)
  36. {
  37. unsigned long long c;
  38. /*
  39. * we have not yet a clock framework for imx6, so add the clock
  40. * value here as a define. Replace it when we have the clock
  41. * framework.
  42. */
  43. c = CONFIG_IMX6_PWM_PER_CLK;
  44. c = c * period_ns;
  45. do_div(c, 1000000000);
  46. *period_c = c;
  47. *prescale = *period_c / 0x10000 + 1;
  48. *period_c /= *prescale;
  49. c = *period_c * (unsigned long long)duty_ns;
  50. do_div(c, period_ns);
  51. *duty_c = c;
  52. /*
  53. * according to imx pwm RM, the real period value should be
  54. * PERIOD value in PWMPR plus 2.
  55. */
  56. if (*period_c > 2)
  57. *period_c -= 2;
  58. else
  59. *period_c = 0;
  60. return 0;
  61. }