pwm-at91.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * PWM support for Microchip AT91 architectures.
  4. *
  5. * Copyright (C) 2021 Microchip Technology Inc. and its subsidiaries
  6. *
  7. * Author: Dan Sneddon <daniel.sneddon@microchip.com>
  8. *
  9. * Based on drivers/pwm/pwm-atmel.c from Linux.
  10. */
  11. #include <clk.h>
  12. #include <common.h>
  13. #include <div64.h>
  14. #include <dm.h>
  15. #include <linux/bitops.h>
  16. #include <linux/io.h>
  17. #include <pwm.h>
  18. #define PERIOD_BITS 16
  19. #define PWM_MAX_PRES 10
  20. #define NSEC_PER_SEC 1000000000L
  21. #define PWM_ENA 0x04
  22. #define PWM_CHANNEL_OFFSET 0x20
  23. #define PWM_CMR 0x200
  24. #define PWM_CMR_CPRE_MSK GENMASK(3, 0)
  25. #define PWM_CMR_CPOL BIT(9)
  26. #define PWM_CDTY 0x204
  27. #define PWM_CPRD 0x20C
  28. struct at91_pwm_priv {
  29. void __iomem *base;
  30. struct clk pclk;
  31. u32 clkrate;
  32. };
  33. static int at91_pwm_calculate_cprd_and_pres(struct udevice *dev,
  34. unsigned long clkrate,
  35. uint period_ns, uint duty_ns,
  36. unsigned long *cprd, u32 *pres)
  37. {
  38. u64 cycles = period_ns;
  39. int shift;
  40. /* Calculate the period cycles and prescale value */
  41. cycles *= clkrate;
  42. do_div(cycles, NSEC_PER_SEC);
  43. /*
  44. * The register for the period length is period_bits bits wide.
  45. * So for each bit the number of clock cycles is wider divide the input
  46. * clock frequency by two using pres and shift cprd accordingly.
  47. */
  48. shift = fls(cycles) - PERIOD_BITS;
  49. if (shift > PWM_MAX_PRES) {
  50. return -EINVAL;
  51. } else if (shift > 0) {
  52. *pres = shift;
  53. cycles >>= *pres;
  54. } else {
  55. *pres = 0;
  56. }
  57. *cprd = cycles;
  58. return 0;
  59. }
  60. static void at91_pwm_calculate_cdty(uint period_ns, uint duty_ns,
  61. unsigned long clkrate, unsigned long cprd,
  62. u32 pres, unsigned long *cdty)
  63. {
  64. u64 cycles = duty_ns;
  65. cycles *= clkrate;
  66. do_div(cycles, NSEC_PER_SEC);
  67. cycles >>= pres;
  68. *cdty = cprd - cycles;
  69. }
  70. /**
  71. * Returns: channel status after set operation
  72. */
  73. static bool at91_pwm_set(void __iomem *base, uint channel, bool enable)
  74. {
  75. u32 val, cur_status;
  76. val = ioread32(base + PWM_ENA);
  77. cur_status = !!(val & BIT(channel));
  78. /* if channel is already in that state, do nothing */
  79. if (!(enable ^ cur_status))
  80. return cur_status;
  81. if (enable)
  82. val |= BIT(channel);
  83. else
  84. val &= ~(BIT(channel));
  85. iowrite32(val, base + PWM_ENA);
  86. return cur_status;
  87. }
  88. static int at91_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
  89. {
  90. struct at91_pwm_priv *priv = dev_get_priv(dev);
  91. at91_pwm_set(priv->base, channel, enable);
  92. return 0;
  93. }
  94. static int at91_pwm_set_config(struct udevice *dev, uint channel,
  95. uint period_ns, uint duty_ns)
  96. {
  97. struct at91_pwm_priv *priv = dev_get_priv(dev);
  98. unsigned long cprd, cdty;
  99. u32 pres, val;
  100. int channel_enabled;
  101. int ret;
  102. ret = at91_pwm_calculate_cprd_and_pres(dev, priv->clkrate, period_ns,
  103. duty_ns, &cprd, &pres);
  104. if (ret)
  105. return ret;
  106. at91_pwm_calculate_cdty(period_ns, duty_ns, priv->clkrate, cprd, pres, &cdty);
  107. /* disable the channel */
  108. channel_enabled = at91_pwm_set(priv->base, channel, false);
  109. /* It is necessary to preserve CPOL, inside CMR */
  110. val = ioread32(priv->base + (channel * PWM_CHANNEL_OFFSET) + PWM_CMR);
  111. val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK);
  112. iowrite32(val, priv->base + (channel * PWM_CHANNEL_OFFSET) + PWM_CMR);
  113. iowrite32(cprd, priv->base + (channel * PWM_CHANNEL_OFFSET) + PWM_CPRD);
  114. iowrite32(cdty, priv->base + (channel * PWM_CHANNEL_OFFSET) + PWM_CDTY);
  115. /* renable the channel if needed */
  116. if (channel_enabled)
  117. at91_pwm_set(priv->base, channel, true);
  118. return 0;
  119. }
  120. static int at91_pwm_set_invert(struct udevice *dev, uint channel,
  121. bool polarity)
  122. {
  123. struct at91_pwm_priv *priv = dev_get_priv(dev);
  124. u32 val;
  125. val = ioread32(priv->base + (channel * PWM_CHANNEL_OFFSET) + PWM_CMR);
  126. if (polarity)
  127. val |= PWM_CMR_CPOL;
  128. else
  129. val &= ~PWM_CMR_CPOL;
  130. iowrite32(val, priv->base + (channel * PWM_CHANNEL_OFFSET) + PWM_CMR);
  131. return 0;
  132. }
  133. static int at91_pwm_probe(struct udevice *dev)
  134. {
  135. struct at91_pwm_priv *priv = dev_get_priv(dev);
  136. int ret;
  137. priv->base = dev_read_addr_ptr(dev);
  138. if (!priv->base)
  139. return -EINVAL;
  140. ret = clk_get_by_index(dev, 0, &priv->pclk);
  141. if (ret)
  142. return ret;
  143. /* clocks aren't ref-counted so just enabled them once here */
  144. ret = clk_enable(&priv->pclk);
  145. if (ret)
  146. return ret;
  147. priv->clkrate = clk_get_rate(&priv->pclk);
  148. return ret;
  149. }
  150. static const struct pwm_ops at91_pwm_ops = {
  151. .set_config = at91_pwm_set_config,
  152. .set_enable = at91_pwm_set_enable,
  153. .set_invert = at91_pwm_set_invert,
  154. };
  155. static const struct udevice_id at91_pwm_of_match[] = {
  156. { .compatible = "atmel,sama5d2-pwm" },
  157. { }
  158. };
  159. U_BOOT_DRIVER(at91_pwm) = {
  160. .name = "at91_pwm",
  161. .id = UCLASS_PWM,
  162. .of_match = at91_pwm_of_match,
  163. .probe = at91_pwm_probe,
  164. .priv_auto = sizeof(struct at91_pwm_priv),
  165. .ops = &at91_pwm_ops,
  166. };