rohm-regulator.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2020 ROHM Semiconductors
  3. #include <linux/errno.h>
  4. #include <linux/mfd/rohm-generic.h>
  5. #include <linux/module.h>
  6. #include <linux/of.h>
  7. #include <linux/regmap.h>
  8. #include <linux/regulator/driver.h>
  9. static int set_dvs_level(const struct regulator_desc *desc,
  10. struct device_node *np, struct regmap *regmap,
  11. char *prop, unsigned int reg, unsigned int mask,
  12. unsigned int omask, unsigned int oreg)
  13. {
  14. int ret, i;
  15. uint32_t uv;
  16. ret = of_property_read_u32(np, prop, &uv);
  17. if (ret) {
  18. if (ret != -EINVAL)
  19. return ret;
  20. return 0;
  21. }
  22. /* If voltage is set to 0 => disable */
  23. if (uv == 0) {
  24. if (omask)
  25. return regmap_update_bits(regmap, oreg, omask, 0);
  26. }
  27. /* Some setups don't allow setting own voltage but do allow enabling */
  28. if (!mask) {
  29. if (omask)
  30. return regmap_update_bits(regmap, oreg, omask, omask);
  31. return -EINVAL;
  32. }
  33. for (i = 0; i < desc->n_voltages; i++) {
  34. /* NOTE to next hacker - Does not support pickable ranges */
  35. if (desc->linear_range_selectors_bitfield)
  36. return -EINVAL;
  37. if (desc->n_linear_ranges)
  38. ret = regulator_desc_list_voltage_linear_range(desc, i);
  39. else
  40. ret = regulator_desc_list_voltage_linear(desc, i);
  41. if (ret < 0)
  42. continue;
  43. if (ret == uv) {
  44. i <<= ffs(desc->vsel_mask) - 1;
  45. ret = regmap_update_bits(regmap, reg, mask, i);
  46. if (omask && !ret)
  47. ret = regmap_update_bits(regmap, oreg, omask,
  48. omask);
  49. break;
  50. }
  51. }
  52. if (i == desc->n_voltages)
  53. pr_warn("Unsupported %s voltage %u\n", prop, uv);
  54. return ret;
  55. }
  56. int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
  57. struct device_node *np,
  58. const struct regulator_desc *desc,
  59. struct regmap *regmap)
  60. {
  61. int i, ret = 0;
  62. char *prop;
  63. unsigned int reg, mask, omask, oreg = desc->enable_reg;
  64. for (i = 0; i < ROHM_DVS_LEVEL_VALID_AMOUNT && !ret; i++) {
  65. int bit;
  66. bit = BIT(i);
  67. if (dvs->level_map & bit) {
  68. switch (bit) {
  69. case ROHM_DVS_LEVEL_RUN:
  70. prop = "rohm,dvs-run-voltage";
  71. reg = dvs->run_reg;
  72. mask = dvs->run_mask;
  73. omask = dvs->run_on_mask;
  74. break;
  75. case ROHM_DVS_LEVEL_IDLE:
  76. prop = "rohm,dvs-idle-voltage";
  77. reg = dvs->idle_reg;
  78. mask = dvs->idle_mask;
  79. omask = dvs->idle_on_mask;
  80. break;
  81. case ROHM_DVS_LEVEL_SUSPEND:
  82. prop = "rohm,dvs-suspend-voltage";
  83. reg = dvs->suspend_reg;
  84. mask = dvs->suspend_mask;
  85. omask = dvs->suspend_on_mask;
  86. break;
  87. case ROHM_DVS_LEVEL_LPSR:
  88. prop = "rohm,dvs-lpsr-voltage";
  89. reg = dvs->lpsr_reg;
  90. mask = dvs->lpsr_mask;
  91. omask = dvs->lpsr_on_mask;
  92. break;
  93. case ROHM_DVS_LEVEL_SNVS:
  94. prop = "rohm,dvs-snvs-voltage";
  95. reg = dvs->snvs_reg;
  96. mask = dvs->snvs_mask;
  97. omask = dvs->snvs_on_mask;
  98. break;
  99. default:
  100. return -EINVAL;
  101. }
  102. ret = set_dvs_level(desc, np, regmap, prop, reg, mask,
  103. omask, oreg);
  104. }
  105. }
  106. return ret;
  107. }
  108. EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);
  109. /*
  110. * Few ROHM PMIC ICs have constrains on voltage changing:
  111. * BD71837 - only buck 1-4 voltages can be changed when they are enabled.
  112. * Other bucks and all LDOs must be disabled when voltage is changed.
  113. * BD96801 - LDO voltage levels can be changed when LDOs are disabled.
  114. */
  115. int rohm_regulator_set_voltage_sel_restricted(struct regulator_dev *rdev,
  116. unsigned int sel)
  117. {
  118. if (rdev->desc->ops->is_enabled(rdev))
  119. return -EBUSY;
  120. return regulator_set_voltage_sel_regmap(rdev, sel);
  121. }
  122. EXPORT_SYMBOL_GPL(rohm_regulator_set_voltage_sel_restricted);
  123. MODULE_LICENSE("GPL v2");
  124. MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
  125. MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");