axp.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Copyright (C) 2020 allwinnertech Ltd.
  3. */
  4. #include <ffs.h>
  5. #include <log.h>
  6. #include <stddef.h>
  7. #include <sunxi_hal_regulator.h>
  8. #include <sunxi_hal_regulator_private.h>
  9. static int voltage2val(struct regulator_desc *info, int voltage, u8 *reg_val)
  10. {
  11. const struct regulator_linear_range *range;
  12. int i;
  13. if (!info->linear_ranges) {
  14. *reg_val = (voltage - info->min_uv + info->step1_uv - 1)
  15. / info->step1_uv;
  16. return 0;
  17. }
  18. for (i = 0; i < info->n_linear_ranges; i++) {
  19. int linear_max_uV;
  20. range = &info->linear_ranges[i];
  21. linear_max_uV = range->min_uV +
  22. (range->max_sel - range->min_sel) * range->uV_step;
  23. if (!(voltage <= linear_max_uV && voltage >= range->min_uV))
  24. continue;
  25. /* range->uV_step == 0 means fixed voltage range */
  26. if (range->uV_step == 0) {
  27. *reg_val = 0;
  28. } else {
  29. *reg_val = (voltage - range->min_uV) / range->uV_step;
  30. }
  31. *reg_val += range->min_sel;
  32. return 0;
  33. }
  34. return -1;
  35. }
  36. static int val2voltage(struct regulator_desc *info, u8 reg_val, int *voltage)
  37. {
  38. const struct regulator_linear_range *range = info->linear_ranges;
  39. int i;
  40. if (!info->linear_ranges) {
  41. *voltage = info->min_uv + info->step1_uv * reg_val;
  42. return 0;
  43. }
  44. for (i = 0; i < info->n_linear_ranges; i++, range++) {
  45. if (!(reg_val <= range->max_sel && reg_val >= range->min_sel))
  46. continue;
  47. *voltage = (reg_val - range->min_sel) * range->uV_step +
  48. range->min_uV;
  49. return 0;
  50. }
  51. return -1;
  52. }
  53. static int axp_regulator_set_voltage(struct regulator_dev *rdev, int target_uV)
  54. {
  55. unsigned char id = REGULATOR_ID(rdev->flag);
  56. struct regulator_desc *pd = (struct regulator_desc *)rdev->private;
  57. struct regulator_desc *info = &pd[id];
  58. u8 val;
  59. if (voltage2val(info, target_uV, &val))
  60. return -1;
  61. val <<= ffs(info->vol_mask) - 1;
  62. return hal_axp_byte_update(rdev, info->vol_reg, val, info->vol_mask);
  63. }
  64. static int axp_regulator_get_voltage(struct regulator_dev *rdev, int *vol_uV)
  65. {
  66. unsigned char id = REGULATOR_ID(rdev->flag);
  67. struct regulator_desc *pd = (struct regulator_desc *)rdev->private;
  68. struct regulator_desc *info = &pd[id];
  69. u8 val;
  70. int ret;
  71. ret = hal_axp_byte_read(rdev, info->vol_reg, &val);
  72. if (ret)
  73. return ret;
  74. val &= info->vol_mask;
  75. val >>= ffs(info->vol_mask) - 1;
  76. if (val2voltage(info, val, vol_uV))
  77. return -1;
  78. return 0;
  79. }
  80. static int axp_regulator_enable(struct regulator_dev *rdev)
  81. {
  82. unsigned char id = REGULATOR_ID(rdev->flag);
  83. struct regulator_desc *pd = (struct regulator_desc *)rdev->private;
  84. struct regulator_desc *info = &pd[id];
  85. u8 reg_val = 0;
  86. reg_val = info->enable_val;
  87. if (!reg_val)
  88. reg_val = info->enable_mask;
  89. return hal_axp_byte_update(rdev, info->enable_reg,
  90. reg_val, info->enable_mask);
  91. }
  92. static int axp_regulator_disable(struct regulator_dev *rdev)
  93. {
  94. unsigned char id = REGULATOR_ID(rdev->flag);
  95. struct regulator_desc *pd = (struct regulator_desc *)rdev->private;
  96. struct regulator_desc *info = &pd[id];
  97. u8 reg_val = 0;
  98. reg_val = info->disable_val;
  99. if (!reg_val)
  100. reg_val = ~info->enable_mask;
  101. return hal_axp_byte_update(rdev, info->enable_reg,
  102. reg_val, info->enable_mask);
  103. }
  104. struct regulator_ops axp_regulator_ops = {
  105. .set_voltage = axp_regulator_set_voltage,
  106. .get_voltage = axp_regulator_get_voltage,
  107. .enable = axp_regulator_enable,
  108. .disable = axp_regulator_disable,
  109. };