regulator-scmi.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-11-21 GuEe-GUI first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #define DBG_TAG "regulator.scmi"
  13. #define DBG_LVL DBG_INFO
  14. #include <rtdbg.h>
  15. struct scmi_regulator
  16. {
  17. struct rt_regulator_node parent;
  18. struct rt_regulator_param param;
  19. struct rt_device dev;
  20. struct rt_scmi_device *sdev;
  21. rt_uint32_t domain_id;
  22. };
  23. #define raw_to_scmi_regulator(raw) rt_container_of(raw, struct scmi_regulator, parent)
  24. static rt_err_t scmi_regulator_set_enable(struct scmi_regulator *sreg, rt_bool_t enable)
  25. {
  26. struct scmi_voltage_config_set_in in =
  27. {
  28. .domain_id = rt_cpu_to_le32(sreg->domain_id),
  29. .config = rt_cpu_to_le32(enable ? SCMI_VOLTAGE_CONFIG_ON : SCMI_VOLTAGE_CONFIG_OFF),
  30. };
  31. struct scmi_voltage_config_set_out out;
  32. struct rt_scmi_msg msg = RT_SCMI_MSG_IN_OUT(SCMI_VOLTAGE_DOMAIN_CONFIG_SET, &in, &out);
  33. return rt_scmi_process_msg(sreg->sdev, &msg) ? : (out.status ? -RT_ERROR : RT_EOK);
  34. }
  35. static rt_err_t scmi_regulator_enable(struct rt_regulator_node *reg_np)
  36. {
  37. struct scmi_regulator *sreg = raw_to_scmi_regulator(reg_np);
  38. return scmi_regulator_set_enable(sreg, RT_TRUE);
  39. }
  40. static rt_err_t scmi_regulator_disable(struct rt_regulator_node *reg_np)
  41. {
  42. struct scmi_regulator *sreg = raw_to_scmi_regulator(reg_np);
  43. return scmi_regulator_set_enable(sreg, RT_FALSE);
  44. }
  45. static rt_bool_t scmi_regulator_is_enabled(struct rt_regulator_node *reg_np)
  46. {
  47. struct scmi_regulator *sreg = raw_to_scmi_regulator(reg_np);
  48. struct scmi_voltage_config_get_in in =
  49. {
  50. .domain_id = rt_cpu_to_le32(sreg->domain_id),
  51. };
  52. struct scmi_voltage_config_get_out out;
  53. struct rt_scmi_msg msg = RT_SCMI_MSG_IN_OUT(SCMI_VOLTAGE_DOMAIN_CONFIG_GET, &in, &out);
  54. return rt_scmi_process_msg(sreg->sdev, &msg) ? RT_FALSE : (out.config == SCMI_VOLTAGE_CONFIG_ON);
  55. }
  56. static rt_err_t scmi_regulator_set_voltage(struct rt_regulator_node *reg_np,
  57. int min_uvolt, int max_uvolt)
  58. {
  59. struct scmi_regulator *sreg = raw_to_scmi_regulator(reg_np);
  60. struct scmi_voltage_level_set_in in =
  61. {
  62. .domain_id = rt_cpu_to_le32(sreg->domain_id),
  63. .voltage_level = rt_cpu_to_le32((max_uvolt + min_uvolt) >> 1),
  64. };
  65. struct scmi_voltage_level_set_out out;
  66. struct rt_scmi_msg msg = RT_SCMI_MSG_IN_OUT(SCMI_VOLTAGE_DOMAIN_LEVEL_SET, &in, &out);
  67. return rt_scmi_process_msg(sreg->sdev, &msg);
  68. }
  69. static int scmi_regulator_get_voltage(struct rt_regulator_node *reg_np)
  70. {
  71. struct scmi_regulator *sreg = raw_to_scmi_regulator(reg_np);
  72. struct scmi_voltage_level_get_in in =
  73. {
  74. .domain_id = rt_cpu_to_le32(sreg->domain_id),
  75. };
  76. struct scmi_voltage_level_get_out out;
  77. struct rt_scmi_msg msg = RT_SCMI_MSG_IN_OUT(SCMI_VOLTAGE_DOMAIN_LEVEL_GET, &in, &out);
  78. return rt_scmi_process_msg(sreg->sdev, &msg) ? : out.voltage_level;
  79. }
  80. static const struct rt_regulator_ops scmi_regulator_voltage_ops =
  81. {
  82. .enable = scmi_regulator_enable,
  83. .disable = scmi_regulator_disable,
  84. .is_enabled = scmi_regulator_is_enabled,
  85. .set_voltage = scmi_regulator_set_voltage,
  86. .get_voltage = scmi_regulator_get_voltage,
  87. };
  88. static rt_err_t scmi_regulator_probe(struct rt_scmi_device *sdev)
  89. {
  90. rt_err_t err;
  91. rt_uint32_t dom_nr;
  92. struct rt_regulator_node *rnp;
  93. struct rt_ofw_node *np, *child_np;
  94. struct scmi_regulator *sregs = RT_NULL, *sreg;
  95. np = rt_ofw_get_child_by_tag(sdev->parent.ofw_node, "regulators");
  96. if (!np)
  97. {
  98. err = -RT_EINVAL;
  99. goto _fail;
  100. }
  101. dom_nr = rt_ofw_get_child_count(np);
  102. if (!dom_nr)
  103. {
  104. err = -RT_EEMPTY;
  105. goto _fail;
  106. }
  107. sregs = rt_calloc(dom_nr, sizeof(*sregs));
  108. if (!sregs)
  109. {
  110. err = -RT_ENOMEM;
  111. goto _fail;
  112. }
  113. sreg = &sregs[0];
  114. rt_ofw_foreach_child_node(np, child_np)
  115. {
  116. if ((err = rt_ofw_prop_read_u32(child_np, "reg", &sreg->domain_id)))
  117. {
  118. goto _fail;
  119. }
  120. sreg->sdev = sdev;
  121. rnp = &sreg->parent;
  122. sreg->dev.ofw_node = child_np;
  123. rt_ofw_prop_read_string(child_np, "regulator-name", &rnp->supply_name);
  124. rnp->ops = &scmi_regulator_voltage_ops;
  125. rnp->param = &sreg->param;
  126. rnp->dev = &sreg->dev;
  127. ++sreg;
  128. }
  129. rt_ofw_node_put(np);
  130. sreg = &sregs[0];
  131. for (int i = 0; i < dom_nr; ++i, ++sreg)
  132. {
  133. if ((err = rt_regulator_register(&sreg->parent)))
  134. {
  135. while (i --> 0)
  136. {
  137. --sreg;
  138. rt_regulator_unregister(&sreg->parent);
  139. }
  140. goto _fail;
  141. }
  142. }
  143. return RT_EOK;
  144. _fail:
  145. rt_ofw_node_put(np);
  146. if (sregs)
  147. {
  148. rt_free(sregs);
  149. }
  150. return err;
  151. }
  152. static const struct rt_scmi_device_id scmi_regulator_ids[] =
  153. {
  154. { SCMI_PROTOCOL_ID_VOLTAGE, "regulator" },
  155. { /* sentinel */ },
  156. };
  157. static struct rt_scmi_driver scmi_regulator_driver =
  158. {
  159. .name = "scmi-regulator",
  160. .ids = scmi_regulator_ids,
  161. .probe = scmi_regulator_probe,
  162. };
  163. RT_SCMI_DRIVER_EXPORT(scmi_regulator_driver);