clk-pwm.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2014 Philipp Zabel, Pengutronix
  4. *
  5. * PWM (mis)used as clock output
  6. */
  7. #include <linux/clk-provider.h>
  8. #include <linux/kernel.h>
  9. #include <linux/module.h>
  10. #include <linux/of.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/pwm.h>
  13. struct clk_pwm {
  14. struct clk_hw hw;
  15. struct pwm_device *pwm;
  16. struct pwm_state state;
  17. u32 fixed_rate;
  18. };
  19. static inline struct clk_pwm *to_clk_pwm(struct clk_hw *hw)
  20. {
  21. return container_of(hw, struct clk_pwm, hw);
  22. }
  23. static int clk_pwm_enable(struct clk_hw *hw)
  24. {
  25. struct clk_pwm *clk_pwm = to_clk_pwm(hw);
  26. return pwm_apply_atomic(clk_pwm->pwm, &clk_pwm->state);
  27. }
  28. static void clk_pwm_disable(struct clk_hw *hw)
  29. {
  30. struct clk_pwm *clk_pwm = to_clk_pwm(hw);
  31. struct pwm_state state = clk_pwm->state;
  32. state.enabled = false;
  33. pwm_apply_atomic(clk_pwm->pwm, &state);
  34. }
  35. static int clk_pwm_prepare(struct clk_hw *hw)
  36. {
  37. struct clk_pwm *clk_pwm = to_clk_pwm(hw);
  38. return pwm_apply_might_sleep(clk_pwm->pwm, &clk_pwm->state);
  39. }
  40. static void clk_pwm_unprepare(struct clk_hw *hw)
  41. {
  42. struct clk_pwm *clk_pwm = to_clk_pwm(hw);
  43. pwm_disable(clk_pwm->pwm);
  44. }
  45. static unsigned long clk_pwm_recalc_rate(struct clk_hw *hw,
  46. unsigned long parent_rate)
  47. {
  48. struct clk_pwm *clk_pwm = to_clk_pwm(hw);
  49. return clk_pwm->fixed_rate;
  50. }
  51. static int clk_pwm_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty)
  52. {
  53. struct clk_pwm *clk_pwm = to_clk_pwm(hw);
  54. struct pwm_state state;
  55. int ret;
  56. ret = pwm_get_state_hw(clk_pwm->pwm, &state);
  57. if (ret)
  58. return ret;
  59. duty->num = state.duty_cycle;
  60. duty->den = state.period;
  61. return 0;
  62. }
  63. static const struct clk_ops clk_pwm_ops_atomic = {
  64. .enable = clk_pwm_enable,
  65. .disable = clk_pwm_disable,
  66. .recalc_rate = clk_pwm_recalc_rate,
  67. .get_duty_cycle = clk_pwm_get_duty_cycle,
  68. };
  69. static const struct clk_ops clk_pwm_ops = {
  70. .prepare = clk_pwm_prepare,
  71. .unprepare = clk_pwm_unprepare,
  72. .recalc_rate = clk_pwm_recalc_rate,
  73. .get_duty_cycle = clk_pwm_get_duty_cycle,
  74. };
  75. static int clk_pwm_probe(struct platform_device *pdev)
  76. {
  77. struct device_node *node = pdev->dev.of_node;
  78. struct clk_init_data init;
  79. struct clk_pwm *clk_pwm;
  80. struct pwm_device *pwm;
  81. struct pwm_args pargs;
  82. const char *clk_name;
  83. int ret;
  84. clk_pwm = devm_kzalloc(&pdev->dev, sizeof(*clk_pwm), GFP_KERNEL);
  85. if (!clk_pwm)
  86. return -ENOMEM;
  87. pwm = devm_pwm_get(&pdev->dev, NULL);
  88. if (IS_ERR(pwm))
  89. return PTR_ERR(pwm);
  90. pwm_get_args(pwm, &pargs);
  91. if (!pargs.period) {
  92. dev_err(&pdev->dev, "invalid PWM period\n");
  93. return -EINVAL;
  94. }
  95. if (of_property_read_u32(node, "clock-frequency", &clk_pwm->fixed_rate))
  96. clk_pwm->fixed_rate = div64_u64(NSEC_PER_SEC, pargs.period);
  97. if (!clk_pwm->fixed_rate) {
  98. dev_err(&pdev->dev, "fixed_rate cannot be zero\n");
  99. return -EINVAL;
  100. }
  101. if (pargs.period != NSEC_PER_SEC / clk_pwm->fixed_rate &&
  102. pargs.period != DIV_ROUND_UP(NSEC_PER_SEC, clk_pwm->fixed_rate)) {
  103. dev_err(&pdev->dev,
  104. "clock-frequency does not match PWM period\n");
  105. return -EINVAL;
  106. }
  107. pwm_init_state(pwm, &clk_pwm->state);
  108. pwm_set_relative_duty_cycle(&clk_pwm->state, 1, 2);
  109. clk_pwm->state.enabled = true;
  110. clk_name = node->name;
  111. of_property_read_string(node, "clock-output-names", &clk_name);
  112. init.name = clk_name;
  113. if (pwm_might_sleep(pwm))
  114. init.ops = &clk_pwm_ops;
  115. else
  116. init.ops = &clk_pwm_ops_atomic;
  117. init.flags = 0;
  118. init.num_parents = 0;
  119. clk_pwm->pwm = pwm;
  120. clk_pwm->hw.init = &init;
  121. ret = devm_clk_hw_register(&pdev->dev, &clk_pwm->hw);
  122. if (ret)
  123. return ret;
  124. return of_clk_add_hw_provider(node, of_clk_hw_simple_get, &clk_pwm->hw);
  125. }
  126. static void clk_pwm_remove(struct platform_device *pdev)
  127. {
  128. of_clk_del_provider(pdev->dev.of_node);
  129. }
  130. static const struct of_device_id clk_pwm_dt_ids[] = {
  131. { .compatible = "pwm-clock" },
  132. { }
  133. };
  134. MODULE_DEVICE_TABLE(of, clk_pwm_dt_ids);
  135. static struct platform_driver clk_pwm_driver = {
  136. .probe = clk_pwm_probe,
  137. .remove = clk_pwm_remove,
  138. .driver = {
  139. .name = "pwm-clock",
  140. .of_match_table = clk_pwm_dt_ids,
  141. },
  142. };
  143. module_platform_driver(clk_pwm_driver);
  144. MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>");
  145. MODULE_DESCRIPTION("PWM clock driver");
  146. MODULE_LICENSE("GPL");