axp209.c 3.9 KB

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