dev_regulator.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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-12-06 GuEe-GUI first version
  9. */
  10. #include "dev_sdio_dm.h"
  11. #define DBG_TAG "SDIO"
  12. #ifdef RT_SDIO_DEBUG
  13. #define DBG_LVL DBG_LOG
  14. #else
  15. #define DBG_LVL DBG_INFO
  16. #endif /* RT_SDIO_DEBUG */
  17. #include <rtdbg.h>
  18. static rt_err_t ocrbitnum_to_vdd(int vdd_bit, int *min_uvolt, int *max_uvolt)
  19. {
  20. int tmp;
  21. if (!vdd_bit)
  22. {
  23. return -RT_EINVAL;
  24. }
  25. tmp = vdd_bit - rt_ilog2(VDD_165_195);
  26. if (tmp == 0)
  27. {
  28. *min_uvolt = 1650 * 1000;
  29. *max_uvolt = 1950 * 1000;
  30. }
  31. else
  32. {
  33. *min_uvolt = 1900 * 1000 + tmp * 100 * 1000;
  34. *max_uvolt = *min_uvolt + 100 * 1000;
  35. }
  36. return 0;
  37. }
  38. rt_err_t sdio_regulator_set_ocr(struct rt_mmcsd_host *host,
  39. struct rt_regulator *supply, rt_uint16_t vdd_bit)
  40. {
  41. rt_err_t err = RT_EOK;
  42. if (!host)
  43. {
  44. return -RT_EINVAL;
  45. }
  46. if (rt_is_err_or_null(supply))
  47. {
  48. return RT_EOK;
  49. }
  50. if (vdd_bit)
  51. {
  52. int min_uvolt, max_uvolt;
  53. ocrbitnum_to_vdd(vdd_bit, &min_uvolt, &max_uvolt);
  54. err = rt_regulator_set_voltage(supply, min_uvolt, max_uvolt);
  55. if (!err && host->supply.regulator_enabled)
  56. {
  57. err = rt_regulator_enable(supply);
  58. if (!err)
  59. {
  60. host->supply.regulator_enabled = RT_TRUE;
  61. }
  62. }
  63. }
  64. else if (host->supply.regulator_enabled)
  65. {
  66. err = rt_regulator_disable(supply);
  67. if (!err)
  68. {
  69. host->supply.regulator_enabled = RT_FALSE;
  70. }
  71. }
  72. if (err)
  73. {
  74. LOG_E("Set regulator OCR %d error = %s", vdd_bit, rt_strerror(err));
  75. }
  76. return err;
  77. }
  78. static int regulator_set_voltage_if_supported(struct rt_regulator *regulator,
  79. int min_uvolt, int target_uvolt, int max_uvolt)
  80. {
  81. if (!rt_regulator_is_supported_voltage(regulator, min_uvolt, max_uvolt))
  82. {
  83. return -RT_EINVAL;
  84. }
  85. if (rt_regulator_get_voltage(regulator) == target_uvolt)
  86. {
  87. return RT_EOK;
  88. }
  89. return rt_regulator_set_voltage_triplet(regulator, min_uvolt, target_uvolt,
  90. max_uvolt);
  91. }
  92. rt_err_t sdio_regulator_set_vqmmc(struct rt_mmcsd_host *host,
  93. struct rt_mmcsd_io_cfg *ios)
  94. {
  95. rt_err_t err;
  96. int uvolt, min_uvolt, max_uvolt;
  97. if (rt_is_err_or_null(host->supply.vqmmc))
  98. {
  99. return -RT_EINVAL;
  100. }
  101. switch (ios->signal_voltage)
  102. {
  103. case MMCSD_SIGNAL_VOLTAGE_120:
  104. return regulator_set_voltage_if_supported(host->supply.vqmmc,
  105. 1100000, 1200000, 1300000);
  106. case MMCSD_SIGNAL_VOLTAGE_180:
  107. return regulator_set_voltage_if_supported(host->supply.vqmmc,
  108. 1700000, 1800000, 1950000);
  109. case MMCSD_SIGNAL_VOLTAGE_330:
  110. err = ocrbitnum_to_vdd(host->io_cfg.vdd, &uvolt, &max_uvolt);
  111. if (err)
  112. {
  113. return err;
  114. }
  115. min_uvolt = rt_max(uvolt - 300000, 2700000);
  116. max_uvolt = rt_min(max_uvolt + 200000, 3600000);
  117. err = regulator_set_voltage_if_supported(host->supply.vqmmc,
  118. min_uvolt, uvolt, max_uvolt);
  119. if (err >= 0)
  120. {
  121. return err;
  122. }
  123. return regulator_set_voltage_if_supported(host->supply.vqmmc,
  124. 2700000, uvolt, 3600000);
  125. default:
  126. return -RT_EINVAL;
  127. }
  128. }
  129. rt_err_t sdio_regulator_get_supply(struct rt_device *dev, struct rt_mmcsd_host *host)
  130. {
  131. rt_err_t err;
  132. if (!dev || !host)
  133. {
  134. return -RT_EINVAL;
  135. }
  136. host->supply.vmmc = rt_regulator_get(dev, "vmmc");
  137. host->supply.vqmmc = rt_regulator_get(dev, "vqmmc");
  138. if (!rt_is_err(host->supply.vmmc))
  139. {
  140. if (!host->supply.vmmc)
  141. {
  142. LOG_D("%s: No %s regulator found", rt_dm_dev_get_name(dev), "vmmc");
  143. }
  144. }
  145. else
  146. {
  147. err = rt_ptr_err(host->supply.vmmc);
  148. goto _fail;
  149. }
  150. if (!rt_is_err(host->supply.vqmmc))
  151. {
  152. if (!host->supply.vqmmc)
  153. {
  154. LOG_D("%s: No %s regulator found", rt_dm_dev_get_name(dev), "vqmmc");
  155. }
  156. }
  157. else
  158. {
  159. err = rt_ptr_err(host->supply.vqmmc);
  160. goto _fail;
  161. }
  162. return RT_EOK;
  163. _fail:
  164. if (!rt_is_err_or_null(host->supply.vmmc))
  165. {
  166. rt_regulator_put(host->supply.vmmc);
  167. host->supply.vmmc = RT_NULL;
  168. }
  169. if (!rt_is_err_or_null(host->supply.vqmmc))
  170. {
  171. rt_regulator_put(host->supply.vqmmc);
  172. host->supply.vqmmc = RT_NULL;
  173. }
  174. return err;
  175. }
  176. rt_err_t sdio_regulator_enable_vqmmc(struct rt_mmcsd_host *host)
  177. {
  178. struct rt_mmcsd_supply *supply;
  179. if (!host)
  180. {
  181. return -RT_EINVAL;
  182. }
  183. supply = &host->supply;
  184. if (!rt_is_err_or_null(supply->vqmmc) && !supply->vqmmc_enabled)
  185. {
  186. rt_err_t err = rt_regulator_enable(supply->vqmmc);
  187. if (err)
  188. {
  189. LOG_E("Enabling vqmmc regulator failed error = %s", rt_strerror(err));
  190. }
  191. else
  192. {
  193. supply->vqmmc_enabled = RT_TRUE;
  194. }
  195. }
  196. return RT_EOK;
  197. }
  198. void sdio_regulator_disable_vqmmc(struct rt_mmcsd_host *host)
  199. {
  200. struct rt_mmcsd_supply *supply;
  201. if (!host)
  202. {
  203. return;
  204. }
  205. supply = &host->supply;
  206. if (!rt_is_err_or_null(supply->vqmmc) && supply->vqmmc_enabled)
  207. {
  208. rt_regulator_disable(supply->vqmmc);
  209. supply->vqmmc_enabled = RT_FALSE;
  210. }
  211. }