axp209.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2012
  4. * Henrik Nordstrom <henrik@henriknordstrom.net>
  5. */
  6. #include <common.h>
  7. #include <command.h>
  8. #include <asm/arch/pmic_bus.h>
  9. #include <axp_pmic.h>
  10. static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div)
  11. {
  12. if (mvolt < min)
  13. mvolt = min;
  14. else if (mvolt > max)
  15. mvolt = max;
  16. return (mvolt - min) / div;
  17. }
  18. int axp_set_dcdc2(unsigned int mvolt)
  19. {
  20. int rc;
  21. u8 cfg, current;
  22. if (mvolt == 0)
  23. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  24. AXP209_OUTPUT_CTRL_DCDC2);
  25. rc = pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC2);
  26. if (rc)
  27. return rc;
  28. cfg = axp209_mvolt_to_cfg(mvolt, 700, 2275, 25);
  29. /* Do we really need to be this gentle? It has built-in voltage slope */
  30. while ((rc = pmic_bus_read(AXP209_DCDC2_VOLTAGE, &current)) == 0 &&
  31. current != cfg) {
  32. if (current < cfg)
  33. current++;
  34. else
  35. current--;
  36. rc = pmic_bus_write(AXP209_DCDC2_VOLTAGE, current);
  37. if (rc)
  38. break;
  39. }
  40. return rc;
  41. }
  42. int axp_set_dcdc3(unsigned int mvolt)
  43. {
  44. u8 cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
  45. int rc;
  46. if (mvolt == 0)
  47. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  48. AXP209_OUTPUT_CTRL_DCDC3);
  49. rc = pmic_bus_write(AXP209_DCDC3_VOLTAGE, cfg);
  50. if (rc)
  51. return rc;
  52. return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_DCDC3);
  53. }
  54. int axp_set_aldo2(unsigned int mvolt)
  55. {
  56. int rc;
  57. u8 cfg, reg;
  58. if (mvolt == 0)
  59. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  60. AXP209_OUTPUT_CTRL_LDO2);
  61. cfg = axp209_mvolt_to_cfg(mvolt, 1800, 3300, 100);
  62. rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, &reg);
  63. if (rc)
  64. return rc;
  65. /* LDO2 configuration is in upper 4 bits */
  66. reg = (reg & 0x0f) | (cfg << 4);
  67. rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg);
  68. if (rc)
  69. return rc;
  70. return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO2);
  71. }
  72. int axp_set_aldo3(unsigned int mvolt)
  73. {
  74. u8 cfg;
  75. int rc;
  76. if (mvolt == 0)
  77. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  78. AXP209_OUTPUT_CTRL_LDO3);
  79. if (mvolt == -1)
  80. cfg = 0x80; /* determined by LDO3IN pin */
  81. else
  82. cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25);
  83. rc = pmic_bus_write(AXP209_LDO3_VOLTAGE, cfg);
  84. if (rc)
  85. return rc;
  86. return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO3);
  87. }
  88. int axp_set_aldo4(unsigned int mvolt)
  89. {
  90. int rc;
  91. static const unsigned int vindex[] = {
  92. 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500,
  93. 2700, 2800, 3000, 3100, 3200, 3300
  94. };
  95. u8 cfg, reg;
  96. if (mvolt == 0)
  97. return pmic_bus_clrbits(AXP209_OUTPUT_CTRL,
  98. AXP209_OUTPUT_CTRL_LDO4);
  99. /* Translate mvolt to register cfg value, requested <= selected */
  100. for (cfg = 15; vindex[cfg] > mvolt && cfg > 0; cfg--);
  101. rc = pmic_bus_read(AXP209_LDO24_VOLTAGE, &reg);
  102. if (rc)
  103. return rc;
  104. /* LDO4 configuration is in lower 4 bits */
  105. reg = (reg & 0xf0) | (cfg << 0);
  106. rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg);
  107. if (rc)
  108. return rc;
  109. return pmic_bus_setbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO4);
  110. }
  111. int axp_init(void)
  112. {
  113. u8 ver;
  114. int i, rc;
  115. rc = pmic_bus_init();
  116. if (rc)
  117. return rc;
  118. rc = pmic_bus_read(AXP209_CHIP_VERSION, &ver);
  119. if (rc)
  120. return rc;
  121. /* Low 4 bits is chip version */
  122. ver &= 0x0f;
  123. if (ver != 0x1)
  124. return -EINVAL;
  125. /* Mask all interrupts */
  126. for (i = AXP209_IRQ_ENABLE1; i <= AXP209_IRQ_ENABLE5; i++) {
  127. rc = pmic_bus_write(i, 0);
  128. if (rc)
  129. return rc;
  130. }
  131. /*
  132. * Turn off LDOIO regulators / tri-state GPIO pins, when rebooting
  133. * from android these are sometimes on.
  134. */
  135. rc = pmic_bus_write(AXP_GPIO0_CTRL, AXP_GPIO_CTRL_INPUT);
  136. if (rc)
  137. return rc;
  138. rc = pmic_bus_write(AXP_GPIO1_CTRL, AXP_GPIO_CTRL_INPUT);
  139. if (rc)
  140. return rc;
  141. rc = pmic_bus_write(AXP_GPIO2_CTRL, AXP_GPIO_CTRL_INPUT);
  142. if (rc)
  143. return rc;
  144. return 0;
  145. }
  146. int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  147. {
  148. pmic_bus_write(AXP209_SHUTDOWN, AXP209_POWEROFF);
  149. /* infinite loop during shutdown */
  150. while (1) {}
  151. /* not reached */
  152. return 0;
  153. }