rohm-regulator.c 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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 (uv == 0) {
  23. if (omask)
  24. return regmap_update_bits(regmap, oreg, omask, 0);
  25. }
  26. for (i = 0; i < desc->n_voltages; i++) {
  27. ret = regulator_desc_list_voltage_linear_range(desc, i);
  28. if (ret < 0)
  29. continue;
  30. if (ret == uv) {
  31. i <<= ffs(desc->vsel_mask) - 1;
  32. ret = regmap_update_bits(regmap, reg, mask, i);
  33. if (omask && !ret)
  34. ret = regmap_update_bits(regmap, oreg, omask,
  35. omask);
  36. break;
  37. }
  38. }
  39. return ret;
  40. }
  41. int rohm_regulator_set_dvs_levels(const struct rohm_dvs_config *dvs,
  42. struct device_node *np,
  43. const struct regulator_desc *desc,
  44. struct regmap *regmap)
  45. {
  46. int i, ret = 0;
  47. char *prop;
  48. unsigned int reg, mask, omask, oreg = desc->enable_reg;
  49. for (i = 0; i < ROHM_DVS_LEVEL_VALID_AMOUNT && !ret; i++) {
  50. int bit;
  51. bit = BIT(i);
  52. if (dvs->level_map & bit) {
  53. switch (bit) {
  54. case ROHM_DVS_LEVEL_RUN:
  55. prop = "rohm,dvs-run-voltage";
  56. reg = dvs->run_reg;
  57. mask = dvs->run_mask;
  58. omask = dvs->run_on_mask;
  59. break;
  60. case ROHM_DVS_LEVEL_IDLE:
  61. prop = "rohm,dvs-idle-voltage";
  62. reg = dvs->idle_reg;
  63. mask = dvs->idle_mask;
  64. omask = dvs->idle_on_mask;
  65. break;
  66. case ROHM_DVS_LEVEL_SUSPEND:
  67. prop = "rohm,dvs-suspend-voltage";
  68. reg = dvs->suspend_reg;
  69. mask = dvs->suspend_mask;
  70. omask = dvs->suspend_on_mask;
  71. break;
  72. case ROHM_DVS_LEVEL_LPSR:
  73. prop = "rohm,dvs-lpsr-voltage";
  74. reg = dvs->lpsr_reg;
  75. mask = dvs->lpsr_mask;
  76. omask = dvs->lpsr_on_mask;
  77. break;
  78. default:
  79. return -EINVAL;
  80. }
  81. ret = set_dvs_level(desc, np, regmap, prop, reg, mask,
  82. omask, oreg);
  83. }
  84. }
  85. return ret;
  86. }
  87. EXPORT_SYMBOL(rohm_regulator_set_dvs_levels);
  88. MODULE_LICENSE("GPL v2");
  89. MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
  90. MODULE_DESCRIPTION("Generic helpers for ROHM PMIC regulator drivers");