pwm_regulator.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * Copyright (C) 2016 Rockchip Electronics Co., Ltd
  3. *
  4. * Based on kernel drivers/regulator/pwm-regulator.c
  5. * Copyright (C) 2014 - STMicroelectronics Inc.
  6. * Author: Lee Jones <lee.jones@linaro.org>
  7. *
  8. * SPDX-License-Identifier: GPL-2.0+
  9. */
  10. #include <common.h>
  11. #include <dm.h>
  12. #include <errno.h>
  13. #include <pwm.h>
  14. #include <power/regulator.h>
  15. #include <libfdt.h>
  16. #include <fdt_support.h>
  17. #include <fdtdec.h>
  18. DECLARE_GLOBAL_DATA_PTR;
  19. struct pwm_regulator_info {
  20. /* pwm id corresponding to the PWM driver */
  21. int pwm_id;
  22. /* the period of one PWM cycle */
  23. int period_ns;
  24. /*
  25. * the polarity of one PWM
  26. * 0: normal polarity
  27. * 1: inverted polarity
  28. */
  29. bool polarity;
  30. struct udevice *pwm;
  31. /* initialize voltage of regulator */
  32. int init_voltage;
  33. /* the maximum voltage of regulator */
  34. int max_voltage;
  35. /* the minimum voltage of regulator */
  36. int min_voltage;
  37. /* the current voltage of regulator */
  38. int volt_uV;
  39. };
  40. static int pwm_regulator_enable(struct udevice *dev, bool enable)
  41. {
  42. struct pwm_regulator_info *priv = dev_get_priv(dev);
  43. return pwm_set_enable(priv->pwm, priv->pwm_id, enable);
  44. }
  45. static int pwm_voltage_to_duty_cycle_percentage(struct udevice *dev, int req_uV)
  46. {
  47. struct pwm_regulator_info *priv = dev_get_priv(dev);
  48. int min_uV = priv->min_voltage;
  49. int max_uV = priv->max_voltage;
  50. int diff = max_uV - min_uV;
  51. return ((req_uV * 100) - (min_uV * 100)) / diff;
  52. }
  53. static int pwm_regulator_get_voltage(struct udevice *dev)
  54. {
  55. struct pwm_regulator_info *priv = dev_get_priv(dev);
  56. return priv->volt_uV;
  57. }
  58. static int pwm_regulator_set_voltage(struct udevice *dev, int uvolt)
  59. {
  60. struct pwm_regulator_info *priv = dev_get_priv(dev);
  61. int duty_cycle;
  62. int ret = 0;
  63. duty_cycle = pwm_voltage_to_duty_cycle_percentage(dev, uvolt);
  64. ret = pwm_set_invert(priv->pwm, priv->pwm_id, priv->polarity);
  65. if (ret) {
  66. dev_err(dev, "Failed to init PWM\n");
  67. return ret;
  68. }
  69. ret = pwm_set_config(priv->pwm, priv->pwm_id,
  70. priv->period_ns, (priv->period_ns / 100) * duty_cycle);
  71. if (ret) {
  72. dev_err(dev, "Failed to configure PWM\n");
  73. return ret;
  74. }
  75. priv->volt_uV = uvolt;
  76. return ret;
  77. }
  78. static int pwm_regulator_ofdata_to_platdata(struct udevice *dev)
  79. {
  80. struct pwm_regulator_info *priv = dev_get_priv(dev);
  81. struct fdtdec_phandle_args args;
  82. const void *blob = gd->fdt_blob;
  83. int node = dev_of_offset(dev);
  84. int ret;
  85. ret = fdtdec_parse_phandle_with_args(blob, node, "pwms", "#pwm-cells",
  86. 0, 0, &args);
  87. if (ret) {
  88. debug("%s: Cannot get PWM phandle: ret=%d\n", __func__, ret);
  89. return ret;
  90. }
  91. priv->period_ns = args.args[1];
  92. priv->polarity = args.args[2];
  93. priv->init_voltage = fdtdec_get_int(blob, node,
  94. "regulator-init-microvolt", -1);
  95. if (priv->init_voltage < 0) {
  96. printf("Cannot find regulator pwm init_voltage\n");
  97. return -EINVAL;
  98. }
  99. ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm);
  100. if (ret) {
  101. debug("%s: Cannot get PWM: ret=%d\n", __func__, ret);
  102. return ret;
  103. }
  104. return 0;
  105. }
  106. static int pwm_regulator_probe(struct udevice *dev)
  107. {
  108. struct pwm_regulator_info *priv = dev_get_priv(dev);
  109. struct dm_regulator_uclass_platdata *uc_pdata;
  110. uc_pdata = dev_get_uclass_platdata(dev);
  111. uc_pdata->type = REGULATOR_TYPE_BUCK;
  112. uc_pdata->mode_count = 0;
  113. priv->max_voltage = uc_pdata->max_uV;
  114. priv->min_voltage = uc_pdata->min_uV;
  115. if (priv->init_voltage)
  116. pwm_regulator_set_voltage(dev, priv->init_voltage);
  117. return 0;
  118. }
  119. static const struct dm_regulator_ops pwm_regulator_ops = {
  120. .get_value = pwm_regulator_get_voltage,
  121. .set_value = pwm_regulator_set_voltage,
  122. .set_enable = pwm_regulator_enable,
  123. };
  124. static const struct udevice_id pwm_regulator_ids[] = {
  125. { .compatible = "pwm-regulator" },
  126. { }
  127. };
  128. U_BOOT_DRIVER(pwm_regulator) = {
  129. .name = "pwm_regulator",
  130. .id = UCLASS_REGULATOR,
  131. .ops = &pwm_regulator_ops,
  132. .probe = pwm_regulator_probe,
  133. .of_match = pwm_regulator_ids,
  134. .ofdata_to_platdata = pwm_regulator_ofdata_to_platdata,
  135. .priv_auto_alloc_size = sizeof(struct pwm_regulator_info),
  136. };